Like Share Discussion Bookmark Smile

J.J. Huang   2020-04-03   Java Java 8   瀏覽次數:次   DMCA.com Protection Status

Java 8 | 接口的默認方法和靜態方法

Java 8使用兩個新概念擴展了接口的含義:默認方法和靜態方法。默認方法使得接口有點類似traits,不過要實現的目標不一樣。默認方法使得開發者可以在 不破壞二進制兼容性的前提下,往現存接口中添加新的方法,即不強制那些實現了該接口的類也同時實現這個新加的方法。

為什麼要有這個特性?

首先,之前的接口是個雙刃劍,好處是面向抽象而不是面向具體編程,缺陷是,當需要修改接口時候,需要修改全部實現該接口的類,目前的java 8之前的集合框架沒有foreach方法,通常能想到的解決辦法是在JDK裡給相關的接口添加新的方法及實現。然而,對於已經發布的版本,是沒法在給接口添加新方法的同時不影響已有的實現。所以引進的默認方法。他們的目的是為了解決接口的修改與現有的實現不兼容的問題。

默認方法和抽象方法之間的區別在於抽象方法需要實現,而默認方法不需要。接口提供的默認方法會被接口的實現類繼承或者覆寫,例子程式碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private interface Defaulable {
// Interfaces now allow default methods, the implementer may or
// may not implement (override) them.
default String notRequired() {
return "Default implementation";
}
}

private static class DefaultableImpl implements Defaulable {
}

private static class OverridableImpl implements Defaulable {
@Override
public String notRequired() {
return "Overridden implementation";
}
}

Defaulable接口使用關鍵字default定義了一個默認方法notRequired()DefaultableImpl類實現了這個接口,同時默認繼承了這個接口中的默認方法;OverridableImpl類也實現了這個接口,但覆寫了該接口的默認方法,並提供了一個不同的實現。

Java 8帶來的另一個有趣的特性是在接口中可以定義靜態方法,例子程式碼如下:

1
2
3
4
5
6
private interface DefaulableFactory {
// Interfaces now allow static methods
static Defaulable create( Supplier< Defaulable > supplier ) {
return supplier.get();
}
}

下面的程式碼片段整合了默認方法和靜態方法的使用場景:

1
2
3
4
5
6
7
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() );
}

輸出的結果為:

1
2
Default implementation
Overridden implementation

由於JVM上的默認方法的實現在字節碼層面提供了支持,因此效率非常高。默認方法允許在不打破現有繼承體系的基礎上改進接口。該特性在官方庫中的應用是:給java.util.Collection接口添加新方法,如stream()parallelStream()forEach()removeIf()等等。

儘管默認方法有這麼多好處,但在實際開發中應該謹慎使用:在復雜的繼承體系中,默認方法可能引起歧義和編譯錯誤。如果你想了解更多細節,可以參考官方文件

默認方法實例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class Java8Tester {
   public static void main(String args[]){
      Vehicle vehicle = new Car();
      vehicle.print();
   }
}
 
interface Vehicle {
   default void print(){
      System.out.println("我是一輛車!");
   }
    
   static void blowHorn(){
      System.out.println("按喇叭!!!");
   }
}
 
interface FourWheeler {
   default void print(){
      System.out.println("我是一輛四輪車!");
   }
}
 
class Car implements Vehicle, FourWheeler {
   public void print(){
      Vehicle.super.print();
      FourWheeler.super.print();
      Vehicle.blowHorn();
      System.out.println("我是一輛汽車!");
   }
}

輸出的結果為:

1
2
3
4
我是一輛車!
我是一輛四輪車!
按喇叭!!!
我是一輛汽車!

註:以上參考了
Java 8 Lambda新語法,簡化程式,增強效能
Java 8 新特性
Java 8的新特性—终极版
现代化 Java - Java8 指南