1)超類優先。如果超類提供了一個具體方法,同名而且有相同參數類型發默認方法會被忽略。
2)接口沖突。如果一個超接口提供了一個默認方法,另一個接口提供了一個同名而且參數類型(不論是否是默認參數)相同的方法,必須覆蓋這個方法來解決沖突。
下面來看第二個規則。考慮另一個包含getName方法的接口:
interface Named { default String getName(){ return getClass().getName() + "_" + hashCode():} }
如果有一個類同時實現了這兩個接口會怎么樣呢?
class Student implements Person,Named { ... }
類會繼承Person和Named接口提供的兩個不一致的getName方法。並不是從中選擇一個,Java編譯器會報告一個錯誤,讓程序員來解決這個二義性。只需要在Student類中提供一個getName方法,在這個方法中,可以選擇兩個沖突方法中發一個,如下所示:
1 class Student implements Person,Named 2 { 3 public String getName(){ return Person.suoer.getName();} 4 ... 5 }
現在假設Named接口沒有為getName提供默認實現:
interface Named { String getName(); }
Students類會從Person接口繼承默認方法嗎?這好像挺有道理,不過,Java設計者更強調一致性。兩個接口如何沖突並不重要。如果至少有一個接口提供了一個實現,編譯器就會報告錯誤,而程序員就必須解決這個二義性。
我們只討論了兩個接口的命名沖突。現在來考慮另一種情況,一個類擴展了一個超類,同時實現了一個接口,並從超類和接口繼承了相同的方法。例如,假設Person是一個類,Student定義為:
class Student extends Person implements Named{...}
在這種情況下,只會考慮超類方法,接口的所有默認方法都會被忽略。在我們的例子中,Student從Person繼承了getName方法,Named接口是否為getName提供了默認實現並不會帶來什么區別。這正是“類優先”規則。