Java8新特性-語言新特性

來源:互聯網
上載者:User

Java8新特性-語言新特性

一、 Lambda運算式和函數式介面
    它允許我們將函數當成參數傳遞給某個方法,或者把代碼本身當作資料處理:函數式開發人員非常熟悉這些概念。很多JVM平台上的語言(Groovy、Scala等)從誕生之日就支援Lambda運算式,但是Java開發人員沒有選擇,只能使用匿名內部類代替Lambda運算式。

    最簡單的Lambda運算式可由逗號分隔的參數列表、->符號和語句塊組成。

1.1.運算式文法:

Lambda運算式用於表示一個函數,所以它和函數一樣,也擁有參數、傳回值、函數體,但它沒有函數名,所以Lambda運算式相當於一個匿名函數。文法如下:

注1:在上面這個代碼中的參數的類型是顯式指定的,當然也可以由編譯器推理得出,例如:

Arrays.asList( "a", "b", "d" ).forEach( e -> System.out.println( e ) );

注2:如果Lambda運算式需要更複雜的語句塊,則可以使用花括弧將該語句塊括起來,類似於Java中的函數體,例如:

Arrays.asList( "a", "b", "d" ).forEach( e -> {
    System.out.print( e );
    System.out.print( e );
} );

注3:Lambda運算式可以引用類成員和局部變數(會將這些變數隱式得轉換成final的),例如下列兩個代碼塊的效果完全相同:

String separator = ",";
Arrays.asList( "a", "b", "d" ).forEach(
    ( String e ) -> System.out.print( e + separator ) );

 
final String separator = ",";
Arrays.asList( "a", "b", "d" ).forEach(
    ( String e ) -> System.out.print( e + separator ) );

1.2.lambda運算式使用

以篩選年齡大於10的Person對象為例:

1.2.1.為Lambda運算式定義函數式介面

@FunctionalInterface
interface FilterProcessor<T>{
    boolean process(T t);
}
    Lambda的設計者們為了讓現有的功能與Lambda運算式良好相容,考慮了很多方法,於是產生了函數介面這個概念。函數介面指的是只有一個函數的介面,這樣的介面可以隱式轉換為Lambda運算式。java.lang.Runnable和java.util.concurrent.Callable是函數式介面的最佳例子。在實踐中,函數式介面非常脆弱:只要某個開發人員在該介面中添加一個函數,則該介面就不再是函數式介面進而導致編譯失敗。為了克服這種代碼層面的脆弱性,並顯式說明某個介面是函數式介面,Java 8 提供了一個特殊的註解@FunctionalInterface(Java 庫中的所有相關介面都已經帶有這個註解了),舉個簡單的函數式介面的定義:

    在為Lambda運算式定義函數式介面時,需要加上註解@FunctionalInterface,該介面只能有一個抽象函數。當該介面中抽象函數個數不是1時就會報錯提示。

    不過有一點需要注意,預設方法和靜態方法(下面會說到)不會破壞函數式介面的定義

1.2.2.實現篩選函數

List<T> filter(List<T> list, FilterProcessor<T> filterProcessor){
    List<T> result = new ArrayList<T>();
    if(filterProcessor.process(t))
        result.add(t);
    return result;
}

filter函數接收一個函數式介面,該參數用於接收一個Lambda運算式。

1.2.3.傳遞Lambda運算式

List<Person> result = filter(list, (Person p)->p.getAge()>10);

直接將Lambda運算式作為參數傳遞給filter的函數式介面即可,從而在result中就能擷取年齡超過10歲的Person對象。

二、介面的預設方法和靜態方法
    Java 8使用兩個新概念擴充了介面的含義:預設方法和靜態方法。

    1.預設方法使得介面有點類似traits,不過要實現的目標不一樣。預設方法使得開發人員可以在 不破壞二進位相容性的前提下,往現存介面中添加新的方法,即不強制那些實現了該介面的類也同時實現這個新加的方法。

    預設方法和抽象方法之間的區別在於抽象方法需要實現,而預設方法不需要。介面提供的預設方法會被介面的實作類別繼承或者覆寫

    2.Java 8帶來的另一個有趣的特性是在介面中可以定義靜態方法,例子代碼如下:

private interface DefaulableFactory {   
    // Interfaces now allow static methods
    static Defaulable create( Supplier< Defaulable > supplier ) {       
        return supplier.get();
    }
}
    由於JVM上的預設方法的實現在位元組碼層面提供了支援,因此效率非常高。預設方法允許在不打破現有繼承體系的基礎上改進介面。該特性在官方庫中的應用是:給java.util.Collection介面添加新方法,如stream()、parallelStream()、forEach()和removeIf()等等。

    儘管預設方法有這麼多好處,但在實際開發中應該謹慎使用:在複雜的繼承體系中,預設方法可能引起歧義和編譯錯誤。

三、方法引用
方法引用使得開發人員可以直接引用現存的方法、Java類的構造方法或者執行個體對象。方法引用和Lambda運算式配合使用,使得java類的構造方法看起來緊湊而簡潔,沒有很多複雜的模板代碼。

下面的例子中,Car類是不同方法引用的例子,可以協助讀者區分四種類型的方法引用。

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 );

四、重複註解
    自從Java 5中引入註解以來,這個特性開始變得非常流行,並在各個架構和項目中被廣泛使用。不過,註解有一個很大的限制是:在同一個地方不能多次使用同一個註解。Java 8打破了這個限制,引入了重複註解的概念,允許在同一個地方多次使用同一個註解。

    在Java 8中使用@Repeatable註解定義重複註解,實際上,這並不是語言層面的改進,而是編譯器做的一個trick,底層的技術仍然相同。

五、更好的類型推斷
    Java 8編譯器在類型推斷方面有很大的提升,在很多情境下編譯器可以推匯出某個參數的資料類型,從而使得代碼更為簡潔。

六、拓寬註解的應用情境
    Java 8拓寬了註解的應用情境。現在,註解幾乎可以使用在任何元素上:局部變數、介面類型、超類和介面實作類別,甚至可以用在函數的異常定義上。

本文永久更新連結地址:https://www.bkjia.com/Linux/2018-02/151054.htm

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.