一攻礼、lambda表達(dá)式
一個(gè)lambda表達(dá)式包含三個(gè)部分:
- 一段代碼
- 參數(shù)
- 自由變量的值痒玩,這里的自由指的是哪些不是參數(shù)并且沒(méi)有在代碼中定義的變量。
示例:
public static void repeat(String text, int count) {
Runnable r = () -> {
for (int i = 0; i < count; i++) {
System.out.println(text);
Thread.yield();
}
};
new Thread(r).start();
}
含有自由變量的代碼塊被稱(chēng)為“閉包”固歪。
內(nèi)部類(lèi)也會(huì)補(bǔ)貨閉合作用域中的值汹胃。在Java 8之前,內(nèi)部類(lèi)只允許訪(fǎng)問(wèn)final的局部變量皮服。為了適應(yīng)lambda表達(dá)式楞艾,這條規(guī)則也被放寬了参咙。一個(gè)內(nèi)部類(lèi)可以訪(fǎng)問(wèn)任何有效的final局部變量--即任何值不會(huì)發(fā)生變化的變量。
二硫眯、默認(rèn)方法
public interface DefaultDemo {
long getId();
default String getName(){
return "name";
};
}
默認(rèn)方法終結(jié)了以前的一種經(jīng)典模式蕴侧,即提供一個(gè)接口,以及一個(gè)實(shí)現(xiàn)接口的大多數(shù)或全部方法的抽象類(lèi)两入,例如Collection/AbstractCollection【幌現(xiàn)在你只需要在接口中實(shí)現(xiàn)那些方法。
如果一個(gè)接口中定義了一個(gè)默認(rèn)方法裹纳,而另一個(gè)父類(lèi)或者接口中又定義了一個(gè)同名的方法择葡,該選擇哪個(gè)呢?Java中的規(guī)則要簡(jiǎn)單得多剃氧,如下:
- 選擇父類(lèi)中的方法敏储。如果一個(gè)父類(lèi)提供了具體的實(shí)現(xiàn)方法,那么接口中具有相同名稱(chēng)和參數(shù)的默認(rèn)方法會(huì)被忽略朋鞍。
- 接口沖突已添。如果一個(gè)父接口提供了一個(gè)默認(rèn)方法,而另一個(gè)接口也提供了一個(gè)具有相同名稱(chēng)和參數(shù)類(lèi)型的方法(不管是不是默認(rèn)方法)滥酥,那么你必須通過(guò)覆蓋該方法來(lái)解決沖突更舞。
三、方法引用
表達(dá)式System.out::println是一個(gè)方法引用坎吻,等同于lambda表達(dá)式x -> System.out.println(x)缆蝉。
::操作符將方法名和對(duì)象或類(lèi)的名字分隔開(kāi)來(lái)。以下是三種主要的使用情況:
- 對(duì)象::實(shí)例方法
- 類(lèi)::靜態(tài)方法
- 類(lèi)::實(shí)例方法
例如:Math::pow等同于(x,y)->Math.pow(x,y)禾怠,String::compareToIgnoreCase等同于(x,y)->x.compareToIgnoreCase(y)返奉。
注意:如果有多個(gè)同名的重載方法,編譯器會(huì)試圖從上下文中找到最匹配的一個(gè)方法吗氏。例如芽偏,有兩個(gè)版本的Math.max方法,一個(gè)接收整型作為參數(shù)弦讽,而另一個(gè)接收double類(lèi)型的值污尉。究竟會(huì)選擇哪一個(gè)方法取決于Math:max被轉(zhuǎn)換為的函數(shù)式接口的方法參數(shù)。同lambda表達(dá)式類(lèi)似往产,方法引用也不會(huì)獨(dú)立存在被碗,他們經(jīng)常被用于轉(zhuǎn)換為函數(shù)式接口的實(shí)例。 8