一、概述:
接口是多個類的公共規范
接口是引用數據類型,其中最突出的特點就是包含:抽象方法
接口不能像class類進行new關鍵字實例化,要實現它的屬性和方法必須讓一個類來實現它,再實例化該類,才能調用接口的方法
二、什么是抽象方法/類?
我們都知道,在Java的繼承關系當中,父類是將多個子類所共同擁有的屬性和方法、行為特征進行抽取,這些屬性和方法中,有的是已經明確實現了的,有的還無法確定,那么我們就可以將其定義成抽象,當具體子類使用該類時才進行具體屬性、方法、行為特征的定義,進行具體化。
用abstract關鍵字來修飾類:public abstract class/abstract class
用abstract來修飾方法:修飾符 abstract 返回值 方法名(參數類型)
舉個例子:動物都有相同的行為動作,吃食和棲息在不同地方的行為,狗狗愛吃骨肉,棲息在狗窩,貓咪愛吃魚兒,棲息在貓窩,那它們都有相同的行為動作,即吃食和棲息
的行為,但行為動作不一樣,那我們就可以把兩個不同的行為定義在抽象類中,並定義成抽象方法
package daily; abstract class abstract_exp { //吃食行為 public abstract void eat();//抽象方法所在的類必須是抽象類,但抽象類可以定義非抽象方法 //棲息行為 public abstract void sleep(); } class dog extends abstract_exp{//一個類實現抽象類、必須重寫抽象類中所有的抽象方法 @Override public void eat() { System.out.println("我是狗狗,我愛吃骨頭!"); } @Override public void sleep() { System.out.println("我是狗狗,我的住在狗窩"); } } class cat extends abstract_exp{//一個類實現抽象類、必須重寫抽象類中所有的抽象方法 @Override public void eat() { System.out.println("我是貓咪,我愛吃魚兒!"); } @Override public void sleep() { System.out.println("我是貓咪,我的住在貓圈"); } } class abstract_main{ public static void main(String[] args) { cat c = new cat(); dog d = new dog(); c.eat(); c.sleep(); d.eat(); d.sleep(); } } 運行結果: 我是貓咪,我愛吃魚兒! 我是貓咪,我的住在貓圈 我是狗狗,我愛吃骨頭! 我是狗狗,我的住在狗窩
二、接口的定義
2.1格式:
public interface 接口名稱
{
//接口內容
}
備注:由類class換成接口interfa后編譯生成的仍然是.java文件,即 .class-->.java
2.2在不同的jdk版本中,接口所能包含的內容:
(1)如果在jdk1.7: 只包含常量、抽象方法
(2)如果在jdk1.8:還能包含靜態、默認方法(默認方法原則上只能在接口中被調用)
(3)如果在jdk1.9:還能包含私有方法
即在任何的jdk版本中,都能在接口中定義抽象(Abstract)方法,接口不包含構造方法、靜態代碼塊、構造代碼塊
2.3接口中方法的定義:
(1)定義原則:
a.接口中定義的抽象方法,必須由public 和 abstract 同時修飾
b.如果不添加,則java會給你自動添加這兩個關鍵字
(2)方法定義格式:
public interface 接口名稱
{
返回值 方法名(參數類型); //默認抽象方法像這樣定義
public abstract 返回值 方法名(參數類型);//實際上是和第一種定義方式一樣。系統會自動添加public abstract,無需添加
public static 返回值 方法名(參數類型){ };/靜態方法的定義,/必須有方法體
private default 返回值 方法值(參數類型){ };//默認方法的定義,必須有方法體,一般只允許在接口內部使用
}
三、使用接口的時候,需要注意事項:
(1)接口是沒有靜態代碼塊或者構造方法的
(2)一個類只能直接繼承一個父類,但能同時實現多個接口,格式:
public class 類名稱/class 類名稱 implements 接口A,..,接口N
(3)一個類實現接口,如果該類不是抽象類的話(抽象類不允許實例化),必須重寫接口中所有的抽象方法
(4)如果一個類在實現的多個接口的時候,存在重復的抽象方法,那么只需要重寫一次即可
(5)如果一個類在實現的多個接口的時候,存在重復的默認方法,那么實現類一定要對沖突進行處理,對默認方法進行重寫
(6)若一個接口中定義了默認方法,而另外一個父類又定義了一個同名的方法時,那么接口中具有相同名稱的方法會被忽略
定義一個接口inter:
package daily; public interface inter { //接口中定義的屬性必須初始化 int i=0; String name="ibear"; char a = 'A'; //定義接口中的靜態方法,不允許子類重寫,一般要private修飾,因為類可以實現多個接口,當多個接口有相同的方法的話,繼承的類會不知道調用哪個方法的 private static void inter_static_method() { System.out.println("我是接口中的靜態方法!"); } //定義接口中的默認方法,原則上該方法只能在該接口中內部使用 default void d(){ System.out.println("我是接口中的默認方法!"); } //定義抽象方法1 public abstract void method_1(); //定義抽象方法2、系統默認支持這種會自動添加public 和 abstract void method_2(); default void nomal_method() { System.out.println("我是接口中的普通方法!"); } }
定義一個classimpint類來實現inter接口:
package daily; public class classimpint implements inter { //實現一個接口必須重寫接口的所有抽象方法,除非這個類是抽象類,但抽象類不允許實例化 @Override public void method_1() { System.out.println("我是繼承的子類,我已經重寫了inter接口的method_1方法"); } @Override public void method_2() { System.out.println("我是繼承的子類,我已經重寫了inter接口的method_2方法"); } //當一個子類實現的多個接口,多個接口中有相同的默認方法名稱時,必須解決沖突,重寫該默認方法,且修飾符要為public @Override public void d(){ System.out.println("我是子類中的默認方法!"); } }
主方法:
package daily; public class date5_10 { public static void main(String[] args) { //調用接口中的屬性,方式:接口名稱.屬性名稱 System.out.println("我是inter接口中的字符屬性:"+inter.a); System.out.println("我是inter接口中的數字屬性:"+inter.i); System.out.println("我是inter接口中的字符串屬性:"+inter.name); //調用接口中的方法,通過子類來實現 classimpint subclass = new classimpint(); subclass.nomal_method(); //調用實現類中的方法 subclass.method_1(); } } 運行結果: 我是inter接口中的字符屬性:A 我是inter接口中的數字屬性:0 我是inter接口中的字符串屬性:ibear 我是接口中的普通方法! 我是繼承的子類,我已經重寫了inter接口的method_1方法
}
}