Lambda 表達式 VS 匿名內(nèi)部類
本節(jié)我們將重點討論下 Lambda 表達式與匿名內(nèi)部類之間除了語法外還有哪些差別。再開始講解之前我們先列出兩者重要的兩點區(qū)別:
- 無標識性: 內(nèi)部類會確保創(chuàng)建一個擁有唯一表示的對象,而 Lambda 表達式的計算結(jié)果有可能有唯一標識,也可能沒有。
- 作用域規(guī)則: 由于內(nèi)部類可以從父類繼承屬性,Lambda 表達式卻不能,所以,內(nèi)部類的作用域規(guī)則比 Lambda 表達式要復雜。(關(guān)于 Lambda 表達式的作用域規(guī)則可以回看 03 節(jié)的內(nèi)容)
我們來看一個例子:
public class TestLambdaAndInnerClass {
public void test(){
//匿名類實現(xiàn)
Runnable innerRunnable = new Runnable(){
@Override
public void run() {
System.out.println("call run in innerRunnable:\t"+this.getClass());
}
};
//Lambda表達式實現(xiàn)
Runnable lambdaRunnable = () -> System.out.println("call run in lambdaRunnable:\t"+this.getClass());
new Thread(innerRunnable).start();
new Thread(lambdaRunnable).start();
}
public static void main(String...s){
new TestLambdaAndInnerClass().test();
}
}
返回結(jié)果為:
call run in innerRunnable: class com.github.x19990416.item.TestLambdaAndInnerClass$1
call run in lambdaRunnable: class com.github.x19990416.item.TestLambdaAndInnerClass
上面的例子分別在內(nèi)部類和 Lambda 表達式中調(diào)用各自的 this 指針。我們發(fā)現(xiàn) Lambda 表達式的 this 指針指向的是其外圍類 TestLambdaAndInnerClass,匿名內(nèi)部類的指針指向的是其本身。(對于 super 也是一樣的結(jié)果)
我們來看下編譯出來的文件:
?

?
其中 TestLambdaAndInnerClass$1.class 是匿名類 innerRunnable 編譯出來的 class 文件,對于 Lambda 表達式 lambdaRunnable 則沒有編譯出具體的 class 文件。
這說明對于 Lambda 表達式而言,編譯器并不認為它是一個完全的類(或者說它是一個特殊的類對象),所以也不具備一個完全類的特征。
Tips: 匿名類的
this、super指針指向的是其自身的實例,而 Lambda 表達式的this、super指針指向的是創(chuàng)建這個 Lambda 表達式的類對象的實例。
1. 無標識性問題
在 Lambda 表達式出現(xiàn)之前,一個 Java 程序的行為總是與對象關(guān)聯(lián),以標識、狀態(tài)和行為為特征。然而 Lambda 表達式則違背了這個規(guī)則。
雖然 Lambda 表達式可以共享對象的一些屬性,但是表示行為是其唯一的用處。由于沒有狀態(tài),所以表示問題也就不那么重要了。在 Java 語言的規(guī)范中對 Lambda 表達式唯一的要求就是必須計算出其實現(xiàn)的相當?shù)暮瘮?shù)接口的實例類。如果 Java 對每個 Lambda 表達式都擁有唯一的表示,那么 Java 就沒有足夠的靈活性來對系統(tǒng)進行優(yōu)化。
2. Lambda 表達式的作用域規(guī)則
匿名內(nèi)部類與大多數(shù)類一樣,由于它可以引用從父類繼承下來的名字,以及聲明在外部類中的名字,所以它的作用域規(guī)則非常復雜。
Lambda 表達式由于不會從父類型中繼承名字,所以它的作用于規(guī)則要簡單很多。除了參數(shù)以外,用在 Lambda 表達式中的名字的含義與表達式外面是一樣的。
由于 Lambda 表達式的聲明就是一個語句塊,所以 this 與 super與表達式外圍環(huán)境的含義一樣,換言之它們指向的是外圍對象的父類對象。
3. 小結(jié)
本節(jié)我們主要討論了 Lambda 表達式與匿名內(nèi)部類的本質(zhì)區(qū)別,其中重要的是要記住 this 和 super 在兩者之間的作用范圍。記住這個作用范圍可以更好的幫助我們理解 Lambda 表達式的作用域,避免我們在使用 Lambda 表達式中由于作用域引起的 bug,這一類的 bug 在實際中定位是非常困難的。
?
在 Java 里面,所有的方法參數(shù)都是有固定類型的,比如將數(shù)字 9 作為參數(shù)傳遞給一個方法,它的類型是 int;字符串 “9” 作為參數(shù)傳遞給方法,它的類型是 String。那么 Lambda 表達式的類型由是什么呢?通過本節(jié)我們學習什么是函數(shù)式接口,它與 Lambda 表達式的關(guān)系。
羽曦 ·
2025 imooc.com All Rights Reserved |