第一個Lambda表達式
在Lambda出現之前秤朗,如果我們需要寫一個多線程可能需要下面這種方式:
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Hello runnable");
}
};
...
thread.start();
上面的例子如果改成使用Lambda就會簡單許多:
Runnable noArgs = ()->System.out.println("Hello Lambda!~");
...
thread.start();
Lambda表達式是一個匿名函數秩仆,將行為像數據一樣傳遞放典,表達式使用->
將參數和主體分開,->
前面是參數部分变逃,后面這是主體部分粗合。
Lambda的其它形式
BinaryOperator<Long> add = (x,y)->x+y;
//OR
BinaryOperator<Long> add = (Long x,Long y)->x+y;
//OR
BinaryOperator<Long> add = (Long x,Long y)->{
x+y;
};
- Lambda表達式使用
()
表示沒有參數。 - 如果Lambda表達式中只包含一個參數幅垮,可省略掉
()
腰池。 - 如果Lambda表達式的主題是一段代碼塊,需要使用
{}
忙芒,該代碼塊與普通的Java代碼塊并無區(qū)別示弓,也可以返回或拋出異常。 - 如果參數的類型可以由編譯器推斷得出可以省略參數類型呵萨,當然你也可以加上奏属。
以上就是Lambda表達式的所有形式了。
那么問題來了:
BinaryOperator<Long> add = (Long x,Long y)->x+y;
是個什么意思潮峦?
這行代碼并不是講個數字相加囱皿,而是創(chuàng)建了一個函數勇婴,用來計算兩個數字相加的結果。而add的類型是
BinaryOperator<Long>
嘱腥,它也不是兩個數字的和耕渴,而是將兩個數字相加的那段代碼。下面的例子展示如何使用這個變量:
BinaryOperator<Long> add = (Long x,Long y)->x+y;
Long res = add.apply(3L, 4L);
System.out.println("res="+res);//輸出:res=7
函數接口
函數接口是只有一個抽象方法的接口齿兔,用作Lambda表達式的類型橱脸。
如Runnable
就是一個函數接口。
新建一個我們自己的函數接口:
public interface AddOperator<T,D> {
long add(T one,D two);
}
使用:
AddOperator<Long,Long> addOperator = ( x, y)->x +y;
System.err.println("Custom function listener res= "+addOperator.add(34L, 65L));
目標類型
目標類型是指Lambda表達式所在上下文環(huán)境的類型愧驱。比如慰技,將Lambda表達式賦值給一個局部變量,或傳遞給一個方法作為參數组砚,局部變量或方法參數的類型就是Lambda表達式的目標類型吻商。
final
如果我們在匿名內部類中引用了所在方法中的局部變量,這是需要局部變量是final
的糟红。
在Lambda中我們不需要將引用的外部局部變量聲明為final
的艾帐,但是該變量只能被賦值一次。
下面的例子中如果我們去掉注釋盆偿,對name再次賦值柒爸,則無法通過編譯,并顯示出錯信息:local variables referenced from a Lambda expression must be final or effectively final.
Lambda表達式引用的局部變量必須是final或即成事實的final事扭。
String name = getUserName();
//name="hi";
button.addActionListener(event->System.out.println("name="+name));
類型推斷
Lambda表達式的類型推斷是Java7中就引入的目標類型推斷的擴展捎稚。
java7中的類型推斷:
List<String> list= new ArrayList<>();
上例中我們并沒有指定ArrayList的范型類型,而是根據list的類型求橄,推斷出了ArrayList的范性類型今野。
如:AddOperator<Long,Long> addOperator = ( x, y)->x +y;