先談一談抽象類和接口的區別
抽象類
可看做是不可實例化的普通類,可以擁有構造方法,可以有main方法
抽象類中的方法可以是抽象方法(抽象方法必須存在於抽象類中),也可以是普通方法、靜態方法
可以聲明變量,不是必須賦初值。
抽象類可以繼承其它類,也可實現接口
抽象類的派生類,必須覆蓋父類中abstract修飾的所有方法
接口
接口僅可繼承其他接口,不可繼承其它類或實現另外的接口
接口中的方法默認爲abstract類型
接口中聲明的變量必須賦初值,且不可再改變,因爲所有變量都是static final類型的
對於JDK7及以前版本:
1. 接口中的方法不可有方法體(因爲默認是抽象方法),不可有靜態方法。
2. 接口的實現類,必須實現接口中的所有方法(包括接口本身的和從其它接口繼承的)
對於JDK8及以後版本:
1. 接口中default方法可有方法體,也可在接口裏寫靜態方法。
2. 接口的實現類,必須實現接口中除default類型的其它所有方法(包括接口本身的和從其它接口繼承的)
再說說default關鍵字:
自Java8加入
用來修飾方法,使得在接口中的方法可以寫入方法體
接口的實現類若沒有實現(也可以叫覆蓋)default類型的方法,則可在實現類中直接調用(接口says:你不覆蓋,那就按這個默認的來了啊)。否則,是正常的覆蓋,實現多態。
個人理解:
1. default的加入,使得我們在接口類中增加方法時,不必一個個地改動實現類了(添加一個default方法時,實現類可以不去管),使得接口和抽象類更爲貼近了一步。
2. 很多的抽象類可以被精簡掉了,實現接口的抽象類中寫的方法體代碼可以直接移到接口中,派生類直接實現接口即可,具體可以看WebMvcConfigurerAdapter被廢棄的例子
附上一個實驗例子,兩個接口是繼承關係,一個類來實現其中一個接口,實驗各種調用:
interface BaseRadio {
void sent(String a,String b);
int port = 9800;
default void close() {
System.out.println(port);
System.out.println("關了");
}
static void prt(){
System.out.println("uvb77");
}
default void open() {
System.out.println("打開");
}
}
interface Radio extends BaseRadio {
void sent();
void sent(int s);
int sent(String a);
@Override
default void close() {
System.out.println(port + 1);
System.out.println("我是Radio重寫的");
}
static void prt(){
System.out.println("uvb76");
}
}
public class TestRadio implements Radio {
@Override
public void sent() {
System.out.println("我是BaseRadio裏的");
}
@Override
public void sent(int s) {
System.out.println("我是BaseRadio裏的");
}
@Override
public int sent(String a) {
System.out.println("我是BaseRadio裏的");
return 0;
}
@Override
public void sent(String a, String b) {
System.out.println("我是Radio裏的!!!!!");
}
@Override
public void close() {
System.out.println(port + 2);
System.out.println("我是TestRadio重寫的");
}
public static void main(String[] args) {
TestRadio testRadio = new TestRadio();
System.out.println("調用實現類覆蓋的default方法,經過了2次覆蓋,已經和原來完全不同了:");
testRadio.close();
System.out.println("實現類調用BaseRadio接口的default方法,就好像自己的方法哦:");
testRadio.open();
System.out.println("打印接口裏聲明的port:" + TestRadio.port);
Radio.prt();
System.out.println("調用接口的靜態方法");
BaseRadio.prt();
}
}
最終輸出如下:
調用實現類覆蓋的default方法,經過了2次覆蓋,已經和原來完全不同了:
9802
我是TestRadio重寫的
實現類調用BaseRadio接口的default方法,就好像自己的方法哦:
打開
打印接口裏聲明的port:9800
uvb76
調用接口的靜態方法
uvb77