簡介
作用
Java8中接口引入了defualt,static兩種方法提供默認實現,徹底打破了接口不能有默認實現的規定
- static
- 讓接口類似於工具類,提供一些靜態方法
- static方法不會被子類繼承
- defualt
- 給接口加入了默認方法實現
- defualt方法會被子類繼承
為什么
當我們寫好一個庫發布出去,很快收到了很多star,是不是開心的不行,可是有一天看到一個issue,確實最初有一個接口設計有缺陷,需要新加一個方法,這時怎么辦呢?
- 直接在過去的接口中新增一個方法?
- 這是在犯罪!
- 使用defualt提供新增方法的默認實現?
- 沒錯,這就是defualt方法的重要運用場景,可以幫助我們向后兼容的同時,不斷演進
影響
這一變動讓接口和抽象類的區別越來越小了
- 一個類只能繼承一個抽象類,但是可以實現多個接口
- 抽象類可以保存一些通用的成員屬性,接口中不能有屬性
也就是說除了我們需要抽象方法的同時還需要一些成員屬性時我們使用抽象類,其他情況我們都應該使用接口。
同時我們應該發現這樣一來Java也相當於有了部分多重繼承的能力,那么我們會遇到臭名昭著的菱形繼承問題么?讓我們在實踐中尋找答案
實踐
static
工具接口
public interface Support {
static void weather(){
System.out.println("晴轉多雲");
}
}
public class Test {
public static void main(String[] args) {
Support.weather();
}
/**
* 輸出:
* 晴轉多雲
*/
}
defualt
運動Sports接口,默認實現了打乒乓,然后Person實現這個接口
public interface Sports {
default void pingPong(){
System.out.println("打乒乓球");
}
}
public class Person implements Sports{
}
public class Test {
public static void main(String[] args) {
new Person().pingPong();
}
/**
* 輸出:
* 打乒乓球
*/
}
多重繼承
defualt的使用真的很簡單,但是多重繼承的情景下表現的如何呢,當多個接口有相同的方法時會如何執行呢,有三大規則,按順序匹配,保證了可靠性。
規則1.類或者父類中聲明的方法的優先級高於任何默認方法
我們新加一個接口有相同的函數簽名
public interface Programs {
default void pingPong(){
System.out.println("觀看乒乓球比賽");
}
}
然后再Person中提供具體實現
public class Person implements Sports{
@Override
public void pingPong() {
System.out.println("我在打乒乓球");
}
}
public class Chinese extends Person implements Programs, Sports{
}
public class Test {
public static void main(String[] args) {
new Chinese().pingPong();
}
/**
* 輸出:
* 我在打乒乓球
*/
}
規則2.同函數簽名的方法中實現得最具體的那個接口的方法
我們新增一個球類運動接口
public interface BallSports extends Sports{
@Override
default void pingPong() {
System.out.println("打乒乓球(球類運動)");
}
}
public class Person implements Sports, BallSports{
}
public class Test {
public static void main(String[] args) {
new Person().pingPong();
}
/**
* 輸出:
* 打乒乓球(球類運動)
*/
}
規則3.顯示聲明
如果上面兩條都不能滿足,那就過不了編譯需要我們顯示聲明怎么執行了,沒有extend,同時Sports,Programs也沒有繼承關系,這時候就只能我們顯示聲明了
public class Person implements Sports, Programs {
@Override
public void pingPong() {
Programs.super.pingPong();
}
}
public class Test {
public static void main(String[] args) {
new Person().pingPong();
}
/**
* 輸出:
* 觀看乒乓球比賽
*/
}