參考文章:
http://blog.csdn.net/yczz/article/details/50896975
https://www.javacodegeeks.com/2014/05/java-8-features-tutorial.html
1、語言的新特性
1.1、Lambda表示式
// 引數型別編譯器推理
Arrays.asList( "a", "b", "d" ).forEach( e -> System.out.println( e ) );
// 引數型別顯示指定
Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.println( e ) );
// 程式碼塊
Arrays.asList( "a", "b", "d" ).forEach( e -> {
System.out.print( e );
System.out.print( e );
} );
// 返回值編譯器推理
Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> e1.compareTo( e2 ) );
// 返回值顯示指定
Arrays.asList( "a", "b", "d" ).sort( ( e1, e2 ) -> {
int result = e1.compareTo( e2 );
return result;
} );
// 變數隱式轉成final
String separator = ",";
Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.print( e + separator ) );
// 變數顯示指定final
final String separator = ",";
Arrays.asList( "a", "b", "d" ).forEach( ( String e ) -> System.out.print( e + separator ) );
1.2、函式式介面@FunctionalInterface
函式式介面指的是隻有一個函式的介面,這樣的介面可以隱式轉換為Lambda表示式。java.lang.Runnable和java.util.concurrent.Callable是函式式介面的最佳例子。
在實踐中,函式式介面非常脆弱:只要某個開發者在該介面中新增一個函式,則該介面就不再是函式式介面進而導致編譯失敗。為了克服這種程式碼層面的脆弱性,並顯式說明某個介面是函式式介面,Java 8 提供了一個特殊的註解@FunctionalInterface
函式式介面的定義:
@FunctionalInterface public interface Functional { void method(); }
不過有一點需要注意,預設方法和靜態方法不會破壞函式式介面的定義,因此如下的程式碼是合法的。
@FunctionalInterface public interface FunctionalDefaultStaticMethods { void method(); default void defaultMethod() { } static void staticMethod() { } }
Lambda表示式的細節,可以參考官方文件:https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
1.3、介面預設方法和靜態方法
預設方法是使用default關鍵字定義的一個預設方法。預設方法和抽象方法之間的區別在於抽象方法需要實現,而預設方法不需要。介面提供的預設方法會被介面的實現類繼承或者覆寫,
例子程式碼如下:
private interface Defaulable { default String notRequired() { return "Default implementation"; } static String staticMethod() { return "static"; } } private static class DefaultableImpl implements Defaulable { } private static class OverridableImpl implements Defaulable { @Override public String notRequired() { return "Overridden implementation"; } }
Defaulable介面使用關鍵字default定義了一個預設方法notRequired()。DefaultableImpl類實現了這個介面,同時預設繼承了這個介面中的預設方法;OverridableImpl類也實現了這個介面,但覆寫了該介面的預設方法,並提供了一個不同的實現。
靜態方法
private interface DefaulableFactory { // Interfaces now allow static methods static Defaulable create( Supplier< Defaulable > supplier ) { return supplier.get(); } }
下面的程式碼片段整合了預設方法和靜態方法的使用場景:
public static void main( String[] args ) { Defaulable defaulable = DefaulableFactory.create( DefaultableImpl::new ); System.out.println( defaulable.notRequired() ); defaulable = DefaulableFactory.create( OverridableImpl::new ); System.out.println( defaulable.notRequired() ); }
這段程式碼的輸出結果如下:
Default implementation
Overridden implementation
由於JVM上的預設方法的實現在位元組碼層面提供了支援,因此效率非常高。預設方法允許在不打破現有繼承體系的基礎上改進介面。該特性在官方庫中的應用是:給java.util.Collection介面新增新方法,如stream()、parallelStream()、forEach()和removeIf()等等。儘管預設方法有這麼多好處,但在實際開發中應該謹慎使用:在複雜的繼承體系中,預設方法可能引起歧義和編譯錯誤。
如果你想了解更多細節,可以參考官方文件:https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html