[TOC] 前言 Java8新特性 Lambda表達式,好像很酷炫的樣子,直接搬運官方文檔: Purpose This tutorial introduces the new lambda expressions included in Java Platform Standard Edition ...
目錄
前言
Java8新特性-Lambda表達式,好像很酷炫的樣子,直接搬運官方文檔:
Purpose
This tutorial introduces the new lambda expressions included in Java Platform Standard Edition 8 (Java SE 8).
Time to Complete
Approximately 1 hour
Introduction
Lambda expressions are a new and important feature included in Java SE 8. They provide a clear and concise way to represent one method interface using an expression. Lambda expressions also improve the Collection libraries making it easier to iterate through, filter, and extract data from a Collection. In addition, new concurrency features improve performance in multicore environments.
所以學習這麼酷炫的東西其實只需要大約一個小時就足夠了;
介紹裡面只有一句重點,其他都是廢話:
Lambada表達式: 它們通過使用表達式來提供一種清晰簡潔的方式來表示方法介面
然而,我還是不知道方法介面是個什麼東西,直到我看完了文檔,才發現這句也是廢話;因為這個得懂了Lambada表達式是什麼了才能理解這句話;
匿名內部類
學習Lambda表達式之前,先感受下匿名內部類使用:
/**創建一個Runnable介面的實例*/
Runnable runnable = new Runnable() {
@Override
public void run() {
//
}
};
/**如果是創建一個線程可以這樣*/
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
//
}
});
以上代碼創建一個線程,我們知道得到一個介面實例只能實例化其實現類,但是這裡我並沒有創建一個具體的實現類,因為我不需要再次使用它;而是使用了匿名類代替,相比之下這樣的做法使得代碼更緊湊簡潔;
函數式介面 和 Lambda表達式語法
函數式介面:
Java8 將只有一個抽象方法的介面叫做 函數式介面
@FunctionalInterface註解只是顯示表示這個介面是函數式介面,在定義函數式介面時就會檢查是否符合函數式介面規範,Java自己實現的函數式介面都有這個註解,所以你懂的,規範是好事情
Lambda表達式語法(三部分組成):
參數列表 -> 方法體
比如: (int x)-> {System.out.println(x);}
實現函數式介面並使用Lambda表達式:
@FunctionalInterface
interface A{
void opration();
}
class B {
void realOpration(A fi){
fi.opration();
}
}
public class Tests {
@Test
public void test(){
/**創建介面A的實例*/
A a = ()-> System.out.println("this is A ");
a.opration();
/**再來試試這個支持Lambda表達式的方法*/
B b = new B();
b.realOpration(()-> System.out.println("this is A"));
}
}
所以Lambda表達式是什麼?
看了上面簡單的demo,所以Lambda表達式幹了什麼事情,System.out.println("this is A ") 就是函數式介面的匿名實現,只是用了一種特殊的非常簡潔的形式來表示而已,那麼這種表示方法就是Lambda表達式;為什麼這麼簡潔,因為它不僅是匿名類,還特麽把方法都匿名了,因為函數式介面只有一個抽象方法,它可以自動將Lambda表達式綁定到函數式介面的抽象方法;
當然這是我個人理解,文檔中可以找到這樣一句話,它是將其類比為方法:
A lambda expression is like a method: it provides a list of formal parameters and a body - an expression or block - expressed in terms of those parameters.
所以它其實就一個匿名類?然而:
@Test
public void test() {
System.out.println(this.getClass().getName());
A a = new A() {
@Override
public void opration() {
System.out.println(this.getClass().getName());
}
};
a.opration();
A a2 = ()->{System.out.println(this.getClass().getName());};
a2.opration();
}
輸出:
Basic.JavaBasicTests
Basic.JavaBasicTests$3
Basic.JavaBasicTests
Process finished with exit code 0
所以這裡可以看出來,匿名類中this關鍵字指向的是匿名類本身對象,而在Lambda表達式中this關鍵字竟然指向當前對象,這也解釋了為了什麼我當初在Lambda表達式中用this關鍵字死活訪問不到函數式介面的預設方法和常量的原因;
實戰應用
再說函數式介面
我們已經知道函數式介面的作用了,但其實我們不需要自己去實現函數介面,Java8已經根據內置了幾種不同類型的函數式介面;
- Predicate: A property of the object passed as argument
- Consumer: An action to be performed with the object passed as argument
- Function: Transform a T to a U
- Supplier: Provide an instance of a T (such as a factory)
- UnaryOperator: A unary operator from T -> T
- BinaryOperator: A binary operator from (T, T) -> T
這裡沒必要一一列舉了,如果自己需要實現一個支持Lambda表達式的方法,只需要選用合適的函數式介面就行了,其實只是一種規範;
下麵一個demo足夠:
Consumer的應用demo
class Class {
private List<Student> list = new ArrayList<>();
public void addStudent(Student student){
list.add(student);
}
public void showStudents(Consumer<Student> consumer){
for (Student student : list){
consumer.accept(student);
}
}
}
class Student{
private String name;
private char sex;
private Double height;
public String getName() {
return name;
}
public Student setName(String name) {
this.name = name;
return this;
}
public char getSex() {
return sex;
}
public Student setSex(char sex) {
this.sex = sex;
return this;
}
}
public class Tests {
@Test
public void test(){
Class clazz = new Class();
clazz.addStudent(new Student().setName("000").setSex('男'));
clazz.addStudent(new Student().setName("002").setSex('女'));
clazz.showStudents((s)-> System.out.println(s.getName()));
}
}
總結
所以總的來說,就是為了簡化代碼,封裝我們的操作,所以引入了函數式介面的概念,而Lambda表達式表示了函數式介面中抽象方法的匿名實現;但是,因為這個介面只有一個抽象方法,因此Lambda表達式可以看做是這個介面的匿名實現;不過和匿名類相比其實還是有很多限制的;
Lambda表達式在Java8中的應用比較多,特別是對集合類的操作;比如sort方法、foreach方法等等;其中Stream API也是一大特點,但是也不過是對函數式介面的具體應用,還有Method Reference(方法引用)這些新特性,詳細的瞭解需要看官方文檔或者源碼,文檔才是最完整和權威的;
綜上:
They provide a clear and concise way to represent one method interface using an expression.
The Java® Language Specification(Java SE 8 Edition)
Java™ Platform API Doc Standard Ed. 8