1.24 Lambda表达式与匿名内部类的联系和区别
Java Lambda 表達式的一個重要用法是簡化某些匿名內部類的寫法,因此它可以部分取代匿名內部類的作用。
Lambda 表達式與匿名內部類的相同點如下:
- Lambda 表達式與匿名內部類一樣,都可以直接訪問 effectively final 的局部變量,以及外部類的成員變量(包括實例變量和類變量)。
- Lambda 表達式創建的對象與匿名內部類生成的對象一樣,都可以直接調用從接口中繼承的默認方法。
下面程序示范了 Lambda 表達式與匿名內部類的相似之處。
@FunctionalInterface interface Displayable {// 定義一個抽象方法和默認方法void display();default int add(int a, int b) {return a + b;} } public class LambdaAndInner {private int age = 12;private static String name = "C語言中文網";public void test() {String url = "http://c.biancheng.net/";Displayable dis = () -> {// 訪問的局部變量 19 System.out.println("url 局部變量為:" + url);// 訪問外部類的實例變量和類變量 21 System.out.println("外部類的 age 實例變量為:" + age); 22 System.out.println("外部類的 name 類變量為:" + name);};dis.display();// 調用dis對象從接口中繼承的add()方法System.out.println(dis.add(3, 5)); }public static void main(String[] args) {LambdaAndInner lambda = new LambdaAndInner();lambda.test();} }輸出結果為:
url 局部變量為:http://c.biancheng.net/ 外部類的 age 實例變量為:12 外部類的 name 類變量為:C語言中文網 8上面程序使用 Lambda 表達式創建了一個 Displayable 的對象,Lambda 表達式的代碼塊中的代碼第 19、21 和 22 行分別示范了訪問“effectively final”的局部變量、外部類的實例變量和類變量。從這點來看, Lambda 表達式的代碼塊與匿名內部類的方法體是相同的。
與匿名內部類相似的是,由于 Lambda 表達式訪問了 url 局部變量,因此該局部變量相當于有一個隱式的 final 修飾,因此同樣不允許對 url 局部變量重新賦值。
當程序使用 Lambda 表達式創建了 Displayable 的對象之后,該對象不僅可調用接口中唯一的抽象方法,也可調用接口中的默認方法,如上面程序代碼第 26 行所示。
Lambda 表達式與匿名內部類主要存在如下區別。
- 匿名內部類可以為任意接口創建實例——不管接口包含多少個抽象方法,只要匿名內部類實現所有的抽象方法即可;但 Lambda表達式只能為函數式接口創建實例。
- 匿名內部類可以為抽象類甚至普通類創建實例;但 Lambda 表達式只能為函數式接口創建實例。
- 匿名內部類實現的抽象方法的方法體允許調用接口中定義的默認方法;但 Lambda 表達式的代碼塊不允許調用接口中定義的默認方法。
對于 Lambda 表達式的代碼塊不允許調用接口中定義的默認方法的限制,可以嘗試對上面的 LambdaAndInner.java 程序稍做修改,在 Lambda 表達式的代碼塊中增加如下一行:
// 嘗試調用接口中的默認方法,編譯器會報錯 System.out.println(add(3, 5));雖然 Lambda 表達式的目標類型 Displayable 中包含了 add() 方法,但 Lambda 表達式的代碼塊不允許調用這個方法;如果將上面的 Lambda 表達式改為匿名內部類的寫法,當匿名內部類實現 display() 抽象方法時,則完全可以調用這個 add() 方法,如下面代碼所示。
public void test() {String url = "http://c.biancheng.net/";Displayable dis = new Displayable() {@Overridepublic void display() {// 訪問的局部變量System.out.println("url 局部變量為:" + url);// 訪問外部類的實例變量和類變量System.out.println("外部類的 age 實例變量為:" + age);System.out.println("外部類的 name 類變量為:" + name);System.out.println(add(3, 5));}};dis.display(); }總結
以上是生活随笔為你收集整理的1.24 Lambda表达式与匿名内部类的联系和区别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 1.23 Lambda表达式的使用
- 下一篇: 1.1 定义字符串