Java8接口增強——默認方法和靜態方法

在jdk8之前,interface之中可以定義變量和方法,變量必須是public、static、final的,方法必須是public、abstract的抽象方法。由於這些修飾符都是默認的,所以在JDK8之前,下面的寫法都是等價的。

public interface JDK8BeforeInterface {

public static final int field1 = 0;

int field2 = 0;

public abstract void method1(int a) throws Exception;

void method2(int a) throws Exception;

}

JDK8及以後,允許我們在接口中定義static方法和default方法。

public interface JDK8Interface {

// static修飾符定義靜態方法

static void staticMethod() {

System.out.println("接口中的靜態方法");

}

// default修飾符定義默認方法

default void defaultMethod() {

System.out.println("接口中的默認方法");

}

}

JAVA8中接口的默認方法

默認方法允許接口方法定義默認實現,子類方法不必須實現此方法而就可以擁有該方法及實現。如下:

public interface DefaultFuncInter {

int getInt();

default String getString(){

return "Default String";

}

}

默認方法的優勢

默認方法主要優勢是提供了一種擴展接口的方法,而不破壞現有代碼。如果一個已經投入使用的接口需要擴展一個新的方法,在JDK8以前,我們必須再該接口的所有實現類中都添加該方法的實現,否則編譯會出錯。如果實現類數量很少且我們有修改的權限,可能工作量會少,但是如果實現類很多或者我們沒有修改代碼的權限,這樣的話就很難解決了。而默認方法提供了一個實現,當沒有顯式提供時就默認採用這個實現,這樣新添加的接口就不會破壞現有的代碼。

默認方法另一個優勢是該方法是可選的,子類可以根據不同的需求而且經override或者採用默認實現。例如我們定義一個集合幾口,其中有增、刪、改等操作,如果我們的實現類90%都是以數組保存數據,那麼我們可以定義針對這些方法給出默認實現,而對於其他非數組集合或者有其他類似業務,可以選擇性複寫接口中默認方法。(由於接口不允許有成員變量,所以本示例旨在說明默認方法的優勢,並不具有生產可能性)具體參照如下代碼:

/**

* 定義接口,幷包含默認實現方法

*/

public interface CollectionDemoInter {

//增加默認實現

default void addOneObj(Object object){

System.out.println("default add");

}

//刪除默認實現

default void delOneObj(Object object){

System.out.println("default del");

}

//更新默認實現

default void updateOneObj(Object object){

System.out.println("default del");

}

//接口定義需要實現方法

String showMsg();

}

/**

* 基於數組的集合實現類,增刪改使用默認方法

*/

public class Collection4Array implements CollectionDemoInter {

@Override

public String showMsg() {

return null;

}

}

/**

* 特殊集合,不允許刪除元素

*/

public class NodelCollection implements CollectionDemoInter {

@Override

public String showMsg() {

return null;

}

@Override

public void delOneObj(Object object){

System.out.println("none del");

}

}

通過上述代碼,大家可以很清楚的發現,如果在接口中定義默認方法,則子類不需要必須實現該默認實現,如果有特殊需求或者需要,則可以Override該實現。

需要注意

如果一個類實現兩個或兩個以上接口,並且多個接口中包含統一默認方法,此時,編譯器將報錯。這種情況,我們必須讓子類Override該方法,否則無法編譯通過

在所有的情況,類實現的優先級高於接口的默認實現,也就是先使用自己類中定義的方法或者是父類中的方法。

如果是一個接口繼承了另外一個接口,2個接口中也包含相同的默認方法,那麼繼承接口的版本具有更高的優先級。比如A擴展了B接口,那麼優先使用A類裡面的test方法。

通過使用super,可以顯式的引用被繼承接口的默認實現,語法如下:InterfaceName.super.methodName()。

接口中的靜態方法

java8中為接口新增了一項功能:定義一個或者更多個靜態方法。類似於類中的靜態方法,接口定義的靜態方法可以獨立於任何對象調用。所以,在調用靜態方法時,不需要實現接口,也不需要接口的實例,也就是說和調用類的靜態方法的方式類似。語法如:接口名字.靜態方法名。

interface A

{

static String getName()

{

return "接口A。。。";

}

}

public class Test implements A

{

public static void main(String[] args)

{

System.out.println(A.getName());

}

}注意,實現接口的類或者子接口不會繼承接口中的靜態方法。static不能和default同時使用。在java8中很多接口中都增加了靜態方法,比如下面代碼:

public class Test

{

public static void test(List list)

{

//直接使用Comparator的靜態方法

list.sort(Comparator.comparing(String::length));

}

public static void main(String[] args)

{

List list = Lists.newArrayList("122","2","32");

test(list);

for (String str : list)

{

System.out.println(str);

}

}

}


分享到:


相關文章: