接口中方法都爲抽象方法。
這句話在JAVA8之前是對的,在JAVA8之後就錯了
傳統的理解是接口只能是抽象方法。但是程序員們在使用中,發現很不方便,實現接口必須重寫所有方法,很麻煩。所以java設計者妥協了,在java8中,支持default和static方法,這樣,實現接口時,可以選擇不對default修飾的方法重寫。
概念:
-
接口提供一個默認實現的方法,並且不強制實現類重寫此方法
-
默認方法使用default關鍵字來修飾
-
default修飾方法只能在接口中使用,在接口種被default標記的方法爲普通方法,可以直接寫方法體。
-
接口中支持定義靜態方法,將關鍵字換成static即可
如果是Java 7,那麼接口中可以包含的內容有:
1. 常量
2. 抽象方法
如果是Java 8,還可以額外包含有:
3. 默認方法default
4. 靜態方法static
如果是Java 9,還可以額外包含有:
5. 私有方法
接口的默認方法
從Java 8開始,接口裏允許定義默認方法。
格式:
public default 返回值類型 方法名稱(參數列表) {
方法體
}
備註:接口當中的默認方法,可以解決接口升級的問題。
接口的靜態方法
從Java 8開始,接口裏允許定義靜態方法。
格式:
public interface InterfaceA {
/**
* 靜態方法
*/
static void showStatic() {
System.out.println("InterfaceA++showStatic");
}
}
注意,實現接口的類或者子接口不會繼承接口中的靜態方法
特點
- 默認方法可以不強制重寫,並且在一個類繼承接口後可以直接使用接口中的默認方法
繼承類可以直接使用接口中的static方法,也可以創建對象後使用接口中的default方法
interface InterfaceA // 定義一個接口
{
default public void otherprint() // 帶方法體的默認方法
{
System.out.println("print default1 methods InterfaceA!");
}
}
class subClass implements InterfaceA //子類InterfaceAB實現接口InterfaceA
{
}
public class Interfacedefault
{
public static void main(String[ ] args)
{
subClass subObj = new subClass( ); //實例化子類對象
subObj.otherprint( ); //調用接口中的默認方法
InterfaceA InterfaceAobj = new subClass(); // 實例化子類對象,賦值給一個接口引用
InterfaceAobj.otherprint( ); //調用接口中的默認方法
}
}
輸出:
注意如果是static靜態方法,類繼承接口後不可以直接用,也就是上方的default改爲static 就會出錯
- 當一個類實現多個接口時,若多個接口中存在相同默認方法(方法名、參數、返回值相同),此時實現類必須要重寫默認方法,否則編譯錯誤
Java中只能繼承一個類,但是可以實現多個接口,當多個接口中有同一個方法時,以前是沒問題的,因爲實現類必須重寫方法。但現在,當多個接口中有同一個用default修飾的方法時,就無法判斷到底實現的是哪個接口的方法。這種情況下,就必須重寫方法。
重寫有兩種實現方法:
- 實現類中自己重寫默認方法
- 實現類使用super關鍵字指定使用哪個接口的默認方法
interface TestInterface1 //定義接口1
{
default void test()
{
System.out.println("TestInterface1");
}
}
interface TestInterface2 //定義接口2
{
default void test()
{
System.out.println("TestInterface2");
}
}
方法1:
class Test implements TestInterface1, TestInterface2
{
@Override
public void test()
{
System.out.println("這是重寫的方法");
}
}
public class test{
public static void main(String[ ] args)
{
Test TestsubObj = new Test ( ); //實例化子類對象
TestsubObj .test( ); //調用接口中的默認方法
}
}
輸出:
方法2:
public class Test implements TestInterface1, TestInterface2
{
@Override
public void test()
{
// 調用TestInterface1接口的默認test()方法
TestInterface1.super.test();
}
}
public class test{
public static void main(String[ ] args)
{
Test TestsubObj = new Test ( ); //實例化子類對象
TestsubObj .test( ); //調用接口中的默認方法
}
}
輸出:
當然,如果A和B的默認方法不同, 實現類C則會隱式繼承了兩個默認方法
- 如果子類繼承父類,父類中有A方法,該子類同時實現的接口中也有A方法,那麼子類會繼承父類的b方法而不是繼承接口中的b方法
子類優先繼承父類的方法, 如果父類沒有相同簽名的方法,才繼承接口的默認方法。
接口A
interface InterfaceA // 定義一個接口
{
default public void test() // 帶方法體的默認方法
{
System.out.println("print default1 methods InterfaceA!");
}
}
類B:
public class B {
public void test()
{
System.out.println("print Class B");
}
}
類Test 繼承類B和接口A
class Test extends B implements InterfaceA{
}
新建一個Test對象,調用test方法 爲類B中的方法
- 實現類中如果重寫了接口的default 默認方法 那麼 實例化子類對象,賦值給接口引用之後,還是使用重寫的默認方法
一個實現了接口的類的對象賦給接口的引用,
“一個接口,多個方法”,展示了Java的動態多態性。
java可以父類引用子類,體現了java的多態性,但是不能子類引用父類,可以從上往下,不可以從下往上
interface InterfaceA // 定義一個接口
{
default void otherprint() // 帶方法體的默認方法
{
System.out.println("print default1 methods InterfaceA!");
}
}
class subClass implements InterfaceA //子類InterfaceAB實現接口InterfaceA
{
public void otherprint() // 帶方法體的默認方法
{
System.out.println("實現類重寫的方法");
}
}
public class trival{
public static void main(String[ ] args)
{
subClass subObj = new subClass( ); //實例化子類對象
subObj.otherprint( ); //調用接口中的默認方法
InterfaceA InterfaceAobj = new subClass(); // 實例化子類對象,賦值給一個接口引用
InterfaceAobj.otherprint( ); //調用接口中的默認方法
}
}
輸出: