關於匿名內部集合和lambda表達式



 
        

要想說清楚JAVA中的Lambda表達式,必須想講一下匿名內部類來幫助理解本質。

一.匿名內部類

  匿名內部類適合創建那種只需要一次使用的類,例如前面介紹命令模式時所需要的Command對象,匿名內部類的語法有點奇怪,創建匿名內部類時會立即創建一個該類的實例,這個類的定義立即消失,匿名內部類不能重復使用。

語法格式一般如下:

new 實現接口() | 父類構造器 (實參列表){

  //匿名內部類的類體部分

}

從上面可以看出,匿名內部類必須繼承一個父類,或者實現一個接口,但最多只能繼承一個父類,或者實現一個接口。

關於匿名內部類還有如下兩條規則:

1.匿名內部類不能是抽象類,因為系統在創建匿名內部類時,會立即創建匿名內部類的對象,因此不允許將匿名內部類定義為抽象類。

2.匿名內部類不能定義構造器(Constructor),由於匿名內部類沒有類名,所以無法定義構造器,但匿名構造類可以定義初始化塊,可以通過實例初始化塊來完成構造函數需要完成的部分。

Example 1:

interface MyInter{
    public String getName();
}

public class AnonymousTest{
    public void test(MyInter i){
        System.out.println("The Content of this function is "+i.getName());
    }

    public static void main(String[] args){
        AnonymousTest ta;
        ta.test(new MyInter(){
            public String getName(){
                 return "Anonymous Content";
            }
    });
}

以上的代碼等價的實現類對象的代碼是:

class AnonymousEqual implements MyInter{
    public String getName(){
        return "Anonymous Class Content";
    }
}

Example 2:

abstract class MyUpperClass{
    private String name;
    public abstract String getName();
    public MyUpperClass(){}
    public MyUpperClass(String s){ name=s; }
}////Abstract instead of Interface

public class AnonymousTest{
    public void test(MyUpperClass m){
        System.out.println("The Content of This Method is "+m.getName());
    }
    //////////////
    public static void main(String[] args){
        AnonymousTest at;
        at.test(new MyUpperClass("Abstract Class Derived Content"){
            public String getName(){
                return "AnonymousClass Derived Content";
            }
        });
    }
}


 

二.Lambda表達式

  Lambda表達式是Java8的重要更新,也是一個被廣大開發者期待已久的新特性。Lambda表達式支持將代碼塊作為參數,Lambda表達式允許使用更簡潔的代碼來創建只有一個抽象方法的接口(這種接口被稱為函數式接口)的實例。

Lambda表達式完全可以用於簡化創建匿名內部類對象,因此可將上面中的Example 1中的代碼改寫成如下的形式。

public class AnonymousTest{
    public void test(MyInter i){
        System.out.println("The Content of This Method is "+i.getName());
    }
    //////////////////
    public static void main(String []args){
        AnonymousTest at;
        at.test(()->new String("Lambda Content"));
    }
}

  從上面的程序之中可以看出,這段代碼之中Lambda表達式所實現的test方法和匿名內部類所實現的test方法是完全等價的,只是不再需要一個繁瑣的代碼塊重新聲明一個匿名類,不需要重新指出所重寫的方法的名字,也不需要給出重寫的方法的返回值類型。
從上面的方法之中可以看出,lambda表達式代替匿名內部類的時候,lambda代碼塊將會實現代替實現抽象類的方法體,lambda表達式的語法主要由三部分構成:

(1)形參列表,如果只有一個參數可以省略括號,當無參數類型時可以使用()或者obj來代替。

(2)箭頭(->)

(3)代碼塊部分,如果代碼只有一行則可以省略掉花括號,不然使用花括號將lambda表達式的代碼部分標記出來。

  Lambda表達式的類型,也被稱為“目標類型(target type)”,lambda表達式的目標類型必須是“函數式接口(functional interface)”。函數式接口代表只包含一個抽象方法的接口。函數式接口可以包含多個默認方法,類方法,但只能聲明一個抽象方法。如果采用匿名類型內部類來創建函數式接口的實例,則只需要實現一個抽象方法,在這種情況下即可采用lambda表達式來創建對象,該表達式創建出來的對象目標就是這個函數接口。(可以用@FunctionalInterface注解來對函數接口實行限制)

##表達式的目標類型必須是明確的函數式接口

##lambda表達式只能為函數式接口創建對象,lambda表達式只能實現一個方法,因此他它只能為只有一個抽象方法的借口(函數式接口)創建對象。

 

另外需要注意的一點是: Object不是函數式接口

為了保證lambda表達式的目標類型是一個明確的函數式接口,可以有如下三種常見的方法:

##將lambda表達式賦值給函數式接口類型的變量

##將lambda表達式當作參數傳遞給需要函數式接口類型的參數的調用方法

##使用函數式接口對lambda表達式進行強制的類型轉換

 

附:

在java.util.function包預定下了大量函數式接口,典型的包含如下4類接口。

***Function:這類接口通常包含一個apply抽象方法,對參數進行處理轉換,然后返回一個新的值。

***Consumer:這類接口通常包含一個accept抽象方法,用於對參數進行處理,但是不返回一個新的值。

***Predicate:這類接口通常包含一個test抽象方方法,通過對參數的處理計算,然后返回一個boolean值

***Supplier:這類接口通常包含一個getAs***抽象方法,這種方法無參數,按照某種邏輯運算返回一個數據值。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM