Java 8 的新特性

(最重要的是接口的擴展 和 支持Lambda表達式)

第一: 關於接口 interface,新增了:可以在接口內實現非抽象的方法,只需要在方法前面加上default關鍵字, 另外在接口內也可以添加static 方法

interface Formula {
    double calculate(int a);
    // 原來接口內只允許上面的抽象方法,現在可以增加下面的具體的方法實現,現在接口就類似於抽象類的功能了。
    default double sqrt(int a) {
        return Math.sqrt(a);
    }
    // 靜態方法
    static double sqrt2(int b) {
        return Math.sqrt(b);
    }

}

看到這個,我想了想,現在Java8 支持接口內增加具體的實現方法,功能和抽象類相似,但是有一個好處,我們都知道java 是單繼承的,但是可以實現多個接口,這樣的話可以近似的實現多繼承的功能表示, 但是注意的是,在使用的時候要小心,仔細考慮是否有使用這個功能的必要,因爲它也會出現類似於多繼承出現的語義問題,(當一個類繼承了多個接口,這些接口口擁有相同名字的 default 聲明的方法,當去調用這個方法時不知道調用哪個方法)

第二: 開始支持Lambda 表達式(匿名函數表達式) ,其實支持這個,就可以在一定程度上方便匿名類的使用,使得代碼簡潔,更加具有可讀性,是類似以自動裝箱拆箱機制類似的語法糖

它的實現是通過將Lambda 表達式 映射到函數式接口上面,下面在第三部分中會詳細講解。

它的作用域跟匿名內部類的作用域大體相同,
匿名內部類只可以訪問外部的final類型的局部變量, 靜態變量 以及內部作用域注意的是
Lambda 表達式可以引用類的成員變量與局部變量(如果這些變量不是final的話,它們會被隱含的轉爲final,這樣效率更高) 但是一旦你在Lambda表達式裏面引用了某個類的成員或者局部變量,就不再允許你在後面對這個成員或者局部變量進行修改了(Lambda表達式內部也不允許進行修改),一旦修改就編譯出錯。

// 支持Lambda表達式之後,代碼的寫法
Collections.sort(names, (String a, String b) -> {
    return b.compareTo(a);
});
// 可以再簡潔一些
Collections.sort(names, (String a, String b) -> b.compareTo(a));
// 對於函數體內只有一行代碼,可以更加簡潔一些,去掉括號
Collections.sort(names, (a, b) -> b.compareTo(a));

//  之前必須要定義一個實現了比較器的接口的類,或者使用一個比較實現接口的匿名類的對象
Collections.sort(names, new Comparator(){
    @Override
    public void compete(String a , String b){
        return b.compareTo(a);
    }
});

第三: 函數式接口,其實這個概念的提出就是爲了更好的支持上面的Lambda表達式,Java 8增加了一種特殊的註解@FunctionalInterface ,用來表示函數式接口。(所謂的函數式接口就是 這個接口內只有唯一的一個抽象方法)。

Lambda 表達式在java中怎樣被識別的呢? 爲什麼在上面的例子中,我們在使用Lambda表達式的裏面不用再寫compete方法, 這是因爲你可以將 匿名函數 看做是一個函數式接口, 當使用這個Lambda表達式的時候,就會自動的進入到這個方法裏面進行調用。
讓我們看看上面例子的具體的一個實現流程吧:
所以在上面的例子中,Collections.sort()方法中的第二個參數是一個Comparator 接口類型的對象,當你將一個Lambda表達式當做第二個參數傳進去的時候,首先,它會檢查你的 Comparator接口是不是一個函數式接口,即判斷這個接口內是否只有一個方法,如果不是,程序報錯,如果是,就自動的把下面的代碼當做是抽象方法的具體實現代碼執行。需要記住的一件事是:默認方法與靜態方法並不影響函數式接口的契約,可以任意使用,這樣的接口也會可以被隱式的轉換爲Lambda表達式

下面的這個例子依舊是一個函數式接口

@FunctionalInterface
public interface FunctionalDefaultMethods {
    void method();
    static void method();     
    default void defaultMethod() {            
    }        
}

Lambda表達式的一個書寫方法:
()-> { }
()裏面傳入參數,這個參數必須要跟接口內的你聲明的抽象方法的參數列表相同, 在上面的例子中,以爲着( )內的參數列表必須跟Comparator
接口中的 compete() 方法中的參數列表相同。

// (String a, String b) 裏的參數必須要跟compete(String a , String b)參數相同, 即 個數相同,類型相同
(String a, String b) -> {
    return b.compareTo(a);
} 
==(等價於)
new Comparator(){
    @Override
    public void compete(String a , String b){
        return b.compareTo(a);
    }
}

另外一個例子,再加深一下體會

// 使用註解表明是一個函數式接口,但是不使用註解其實也是可以的,只要裏面只有一個抽象的方法,就可以認爲是一個函數式接口
@FunctionalInterface 
interface Converter<F, T> {
    T convert(F from);
}
Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
Integer converted = converter.convert("123");
System.out.println(converted);    // 123

第四: 方法與構造函數的引用
Java 8 允許你使用 :: 關鍵字來傳遞方法或者構造函數引用,
方法引用提供了非常有用的語法,可以直接引用已有Java類或對象(實例)的方法或構造器。與lambda聯合使用,方法引用可以使語言的構造更緊湊簡潔,減少冗餘代碼。
我們知道,在java的內存模型中,虛擬棧中保存了八種基本數據類型和對象的引用,然後一般通過對象引用去調用對象的時候一般有兩種實現方式:
第一: 通過維護一個句柄池, 對象的引用–> 句柄池 —>實際對象
第二: 指針引用直接指向對象

下面,我們以定義了4個方法的Car這個類作爲例子,區分Java中支持的4種不同的方法引用。

public static class Car {
    public static Car create( final Supplier< Car > supplier ) {
        return supplier.get();
    }              

    public static void collide( final Car car ) {
        System.out.println( "Collided " + car.toString() );
    }

    public void follow( final Car another ) {
        System.out.println( "Following the " + another.toString() );
    }

    public void repair() {   
        System.out.println( "Repaired " + this.toString() );
    }
}

第一種方法引用是構造器引用,它的語法是Class::new,或者更一般的Class< T >::new。請注意構造器沒有參數。

final Car car = Car.create( Car::new );
final List< Car > cars = Arrays.asList( car );

第二種方法引用是靜態方法引用,它的語法是Class::static_method。請注意這個方法接受一個Car類型的參數。

cars.forEach( Car::collide );

第三種方法引用是特定類的任意對象的方法引用,它的語法是Class::method。請注意,這個方法沒有參數。

cars.forEach( Car::repair );

最後,第四種方法引用是特定對象的方法引用,它的語法是instance::method。請注意,這個方法接受一個Car類型的參數

final Car police = Car.create( Car::new );
cars.forEach( police::follow );

除此之外,還有一些新的特性:
支持重複註解
更好的類型推測機制
擴展註解的支持

部分內容參考自:
http://www.jb51.net/article/48304.htm
http://www.importnew.com/11908.html#defaultAndStaticMethod

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章