您好,登錄后才能下訂單哦!
這篇文章主要介紹了Java的接口使用實例分析的相關(guān)知識,內(nèi)容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇Java的接口使用實例分析文章都會有所收獲,下面我們一起來看看吧。
一圖流
接口(英文:Interface),在JAVA編程語言中是一個抽象類型,是抽象方法的集合,接口通常以interface來聲明。一個類通過繼承接口的方式,從而來繼承接口的抽象方法。
接口并不是類,編寫接口的方式和類很相似,但是它們屬于不同的概念。類描述對象的屬性和方法。接口則包含類要實現(xiàn)的方法。
除非實現(xiàn)接口的類是抽象類,否則該類要定義接口中的所有方法。
接口無法被實例化,但是可以被實現(xiàn)。一個實現(xiàn)接口的類,必須實現(xiàn)接口內(nèi)所描述的所有方法,否則就必須聲明為抽象類。另外,在 Java 中,接口類型可用來聲明一個變量,他們可以成為一個空指針,或是被綁定在一個以此接口實現(xiàn)的對象。
一個接口中可以有多個
接口文件保存在.Java結(jié)尾的文件中,文件名使用接口名
接口的字節(jié)碼文件保存在.class結(jié)尾的文件中
接口相應的字節(jié)碼文件必須在與包名稱相匹配的目錄結(jié)構(gòu)中
接口不能用于實例化對象
接口沒有構(gòu)造方法
接口中所有的方法必須是抽象方法,在Java8之后接口中可以使用default關(guān)鍵字修飾的非抽象方法
接口不能包含成員變量,除了static和final變量
接口被類繼承這個概念不準確,準確來說應該是要被類實現(xiàn)
接口可以實現(xiàn)我們所說的多繼承
接口中每一個方法也是隱式抽象的,所以接口中的方法會被隱式得指定為public abstract (只可以是public abstract,其他修飾符都會報錯)
接口中含有變量,但是接口中得變量會被隱式的指定為public static final 變量(并且只能是public,用private修飾會報編譯錯誤)
接口中的方法是不能在接口中實現(xiàn)的,只能由實現(xiàn)接口的類來實現(xiàn)接口中的方法
在JDK1.8以前,它們有如下區(qū)別
抽象類中的方法可以有具體可執(zhí)行的語句,即方法體,就是能實現(xiàn)方法的具體功能,但是接口中的方法就不行(比如:System.out.println(“I’m super corn!!”);)
抽象類中的成員變量可以是各種類型的,而接口中的成員變量只能是public static final類型的
接口中不能含有靜態(tài)代碼塊以及靜態(tài)方法的使用(用static修飾的方法),而抽象類可以有靜態(tài)代碼塊和靜態(tài)方法
一個類只能繼承一個抽象類,而一個類卻可以實現(xiàn)多個接口
那么這里要注意的是:
JDK1.8以后,接口中允許含有靜態(tài)方法和方法體,允許包含具體實現(xiàn)的方法,該方法我們稱之為“默認方法”,這種方法使用default關(guān)鍵字來修飾
JDK1.9以后,允許將方法定義為private,使某些復用的代碼不會將方法暴露出去
抽象類存在的意義是為了讓編譯器更好地校驗,一般抽象類我們不會直接使用,而是使用它的子類,如果不小心通過抽象類創(chuàng)建了對象,編譯器就會及時提醒我們。
注意:以上內(nèi)容大致瀏覽一遍即可,看不懂沒關(guān)系,下面我將為你一一講解,然后回頭再來看這些知識點將會有一種大夢初醒的感覺
那么在現(xiàn)實生活中,接口是什么呢?它可以是筆記本上的USB口,電源插座等
那么這些接口在實現(xiàn)意義上以及使用標準上也有所不同
電腦的USB口上,可以插:U盤、鼠標、鍵盤…所有符合USB協(xié)議的設備
電源插座插孔上,可以插:電腦、電視機、電飯煲…所有符合規(guī)范的設備
通過上述的例子我們就可以看出:接口就是公共的行為規(guī)范標準,大家在實現(xiàn)時,只要符合規(guī)范標準,就可以通用。在Java中,接口可以看成是:多個類的公共規(guī)范,是一種引用數(shù)據(jù)類型
接口的定義格式與定義類的格式基本上相同,將class關(guān)鍵字換成interface關(guān)鍵字就定義了一個接口。
public interface 接口名稱{ //抽象方法 public abstract void method1(); //public abstract是固定搭配,可以不寫 public void method2(); abstract void method3(); void method4(); //注意:在接口中上述的寫法都是抽象方法,所以method4這樣寫代碼更整潔}
提示:
創(chuàng)建接口時,接口的命名一般以大寫字母I(讀ai)開頭
接口的命名一般使用形容詞詞性的單詞
阿里編碼規(guī)范中約定,接口中的方法和屬性不要加任何修飾符,保持代碼的整潔性
接口不能直接實例化使用,必須要有一個類去實現(xiàn)它,實現(xiàn)接口中所有的抽象方法
public class 類名稱 implements 接口名稱{ //...}
注意:子類和父類之間是extends繼承關(guān)系,類與接口之間是implements實現(xiàn)關(guān)系。
筆記本電腦中使用USB鼠標,USB鍵盤的類和接口實現(xiàn)功能
USB接口:包含打開設備、關(guān)閉設備的功能
筆記本類:包含開關(guān)機功能、使用USB設備功能
鼠標類:實現(xiàn)USB接口,并具備點擊功能
鍵盤類:實現(xiàn)USB接口,并具備輸入功能
//USB接口public interface USB{ void openDevice(); void closeDevice();}//鼠標類,實現(xiàn)USB接口public class Mouse implements USB{ @Override public void openDevice(){ System.out.println("打開鼠標"); } @Override public void closeDevice(){ System.out.println("關(guān)閉鼠標"); } public void click(){ System.out.println("鼠標點擊"); }}//鍵盤類,實現(xiàn)USB接口public class KeyBoard implements USB { @Override public void openDevice(){ System.out.println("打開鍵盤"); } @Override public void closeDevice(){ System.out.println("關(guān)閉鍵盤"); } public void inPut(){ System.out.println("鍵盤輸入"); }}//筆記本類:使用USB設備public class Computer { public void powerOn(){ System.out.println("打開筆記本電腦"); } public void powerOff(){ System.out.println("關(guān)閉筆記本電腦"); } public void useDevice(USB usb){ usb.openDevice(); if(usb instanceof Mouse){ Mouse mouse = (Mouse)usb; mouse.click(); }else if(usb instanceof KeyBoard){ KeyBoard keyBoard = (KeyBoard)usb; keyBoard.inPut(); } usb.closeDevice(); }}//測試類:public class TestUSB{ public static void main(String[] args){ Computer computer = new Computer(); computer.powerOn(); //使用鼠標設備 computer.useDevice(new Mouse()); //使用鍵盤設備 computer.useDevice(new KeyBoard()); computer.powerOff(); }}
輸出:
上面的代碼示例中,提到了instanceof,可能有小伙伴不太理解,我在前面的博客中有介紹,這里再重新為大家講解一下
instanceof是Java的一個保留關(guān)鍵字,左邊為對象,右邊為類,返回類型是Boolean類型。
它的具體作用是測試左邊的對象是否是右邊類或者右邊類的子類創(chuàng)建的實例化對象
如果是,則返回true,否則返回false
【instanceof使用注意事項】
現(xiàn)有繼承關(guān)系,再有instanceof的使用(包括接口的實現(xiàn))
【instanceof應用場景】
需要用到對象的強制類型轉(zhuǎn)換時,需要使用instanceof進行判斷
接口類型是一種引用類型,但是不能直接new接口的對象
public class TestUSB { public static void main(String[] args){ USB usb = new USB(); }}//編譯會出錯:USB是抽象的,無法實例化
接口中每一個方法都是public的抽象方法,即接口中的方法會被隱式地指定為public abstract(只能是public abstract,其他修飾符都會報錯)
public interface USB { //編譯出錯:此處不允許使用修飾符private //或者是java: 缺少方法主體, 或聲明抽象 private void openDevice(); void closeDevice(); //不同JDK版本編譯器的標準是不一樣的,報錯也是不一樣的}
接口中的方法是不能在接口中實現(xiàn)的,只能由實現(xiàn)接口的類來實現(xiàn)
public interface USB { void openDevice(); //編譯失?。阂驗榻涌谥械姆椒J為抽象方法 //Error:接口抽象方法不能帶有主體}
但這里如果我們加上一個default,那么就可以實現(xiàn)方法體了。
重寫接口中的方法時,不能使用default作為訪問權(quán)限修飾
public interface USB {void openDevice();//默認為publicvoid closeDevice();//默認為public}public class Mouse implements USB { @Override void openDevice(){ System.out.println("打開鼠標"); } //...}//這里編譯會報錯,重寫USB中的openDevice方法時,不能使用默認修飾符
實現(xiàn)這個接口,重寫這個接口的方法的訪問限定修飾符范圍要比接口中的更大
接口中可以含有變量,但是接口中的變量會被編譯器自動隱式指定為public static final變量
public interface USB { double brand = 3.0;//默認為:final public static修飾 void openDevice(); void closeDevice();}public class TestUSB { public static void main(String[] args){ System.out.println(USB.brand); //可以直接通過接口名訪問,說明變量時靜態(tài)的 //下面寫法會報錯 Java:無法為最終變量brand分配值 USB.brand = 2.0; //說明brand具有final屬性 }}
接口中不能有靜態(tài)代碼塊和構(gòu)造方法
public interface USB { public USB(){ }//編譯失敗 { }//編譯失敗 void openDevice(); void closeDevice();}
接口雖然不是類,但是接口編譯完成之后的字節(jié)碼文件的后綴格式也是.class
如果類沒有實現(xiàn)接口中的所有抽象方法,則類必須設置為抽象類
JDK8中規(guī)定了接口中可以包含上面所說的default方法
在Java中,類和類之間是單繼承的,一個類只能由一個父類,即Java中不支持多繼承,但是一個類可以實現(xiàn)多個接口。下面用代碼來演示
public class Animal { protected String name; public Animal(String name){ this.name = name; }}
然后我們再寫一組接口,分別來表示“會飛的”“會跑的”“會游泳的”.
public interface IFlying { void fly();}public interface IRunning { void run();}public interface ISwimming { void swim();}
那么接下來我們創(chuàng)建幾個具體的動物類來接受并實現(xiàn)這些接口
比如,貓會跑
public class Cat extends Animal implements IRunning{ public Cat(String name) { super(name); } @Override public void run() { System.out.println("小貓"+this.name+"正在跑"); }}
魚會游泳
public class Fish extends Animal implements ISwimming{ public Fish(String name){ super(name); } @Override public void swim() { System.out.println("小魚"+this.name+"正在游泳"); }}
而青蛙即會跑又會游泳
public class Frog extends Animal implements IRunning,ISwimming{ public Frog(String name){ super(name); } @Override public void run() { System.out.println("青蛙"+this.name+"正在跑"); } @Override public void swim() { System.out.println("青蛙"+this.name+"正在游泳"); }}
注意:一個類實現(xiàn)多個接口的時候,每個接口中的抽象方法都要去實現(xiàn),除非類用abstract修飾,為抽象類
提示IDEA中使用ctrl + i 可以快速實現(xiàn)接口
還有一種動物水陸空三棲,它是大白鵝
public class Goose extends Animal implements IRunning,ISwimming,IFlying{ public Goose(String name) { super(name); } @Override public void fly() { System.out.println(this.name+"正在飛"); } @Override public void run() { System.out.println(this.name+"正在跑"); } @Override public void swim() { System.out.println(this.name+"正在漂在水上"); }}
這段代碼展現(xiàn)了Java面向?qū)ο缶幊讨凶畛R姷挠梅ǎ阂粋€類繼承了一個父類,然后同時實現(xiàn)多個接口
繼承表達的含義是is-a,而接口表達的含義是具有xxx的特性
貓是一種動物,具有會跑的特性
青蛙是一種動物,即能跑也能有用
大白鵝也是一種動物,技能跑,也能游,還能飛
有了接口之后,類的使用者就不需要去關(guān)注具體的類的屬性是否符合,而只需要關(guān)心某個類是否具有某個特性/功能,如果有,就可以實現(xiàn)對應的接口
那么我們現(xiàn)在實現(xiàn)一個走路的方法
public class TestDemo1 { public static void walk(IRunning iRunning){ System.out.println("我?guī)е』锇槿ド⒉?quot;); iRunning.run(); } public static void main(String[] args) { Cat cat = new Cat("小貓"); walk(cat); Frog frog = new Frog("小青蛙"); walk(frog); }}
輸出結(jié)果
只要是會跑的,帶有跑這個屬性特征的,都可以接受相應的對象
public class Robot implements IRunning{ private String name; public Robot(String name){ this.name = name; } @Override public void run() { System.out.println(this.name+"正在用輪子跑"); } public static void main(String[] args) { Robot robot = new Robot("機器人"); walk(robot); }}
故輸出結(jié)果為
在Java中,類和類之間是單繼承的,一個類可以實現(xiàn)多個接口,接口與接口之間可以多繼承。
即:用接口可以達到多繼承的目的
接口可以繼承一個接口,達到復用的效果。這里使用extends關(guān)鍵字
interface IRunning { void run();}interface ISwimming { void swim();}//兩棲的動物,即能跑,也能游泳interface IAmphibious extends IRunning ISwimming {}class Frog implements IAmphibious { ...}
通過接口繼承創(chuàng)建一個新的接口IAmphibious表示“兩棲的”。
創(chuàng)建的Frog類就實現(xiàn)了這個兩棲的接口
接口之間的繼承就相當于把多個接口合并到了一起
我們在之前的數(shù)組中講解過給數(shù)組排序,那么我們該如何給對象數(shù)組排序呢?
首先我們定義一個Student的類,然后重寫一下String方法
public class Student { private String name; private int score; public Student(String name,int score){ this.name = name; this.score = score; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", score=" + score + '}'; }}
我們再給定一個學生對象數(shù)組,根據(jù)這個對象數(shù)組中的元素進行排序
這里我們按照分數(shù)降序排序
public class Student { private String name; private int score; public Student(String name,int score){ this.name = name; this.score = score; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", score=" + score + '}'; } public static void main(String[] args) { Student[] students = new Student[]{ new Student("A",95), new Student("B",96), new Student("C",97), new Student("D",98), }; }}
那么按照我們之前的理解,數(shù)組中有一個可以供我們使用的sort方法,我們能否直接使用呢?
Arrays.sort(students);System.out.println(students);//運行結(jié)果:Exception in thread "main" java.lang.ClassCastException: class ClassArray.Student cannot be cast to class java.lang.Comparable (ClassArray.Student is in unnamed module of loader 'app'; java.lang.Comparable is in module java.base of loader 'bootstrap') at java.base/java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:320) at java.base/java.util.ComparableTimSort.sort(ComparableTimSort.java:188) at java.base/java.util.Arrays.sort(Arrays.java:1041) at ClassArray.Student.main(Student.java:36)
我們可以看到這里程序報錯了,這里的意思是Student并沒有實現(xiàn)Comparable的接口
那么這里的sort是進行普通數(shù)字的比較,大小關(guān)系明確,而我們指定的是兩個學生對象的引用變量,這樣的大小關(guān)系的指定是錯誤的,我們需要額外去人為規(guī)定對象中的比較元素
那么怎么實現(xiàn)呢?
我們可以用Student類實現(xiàn)Comparable接口,并實現(xiàn)其中的compareTo方法
public class Student implements Comparable<Student>{ private String name; private int score; public Student(String name,int score){ this.name = name; this.score = score; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", score=" + score + '}'; } @Override public int compareTo(Student o) { if (this.score>o.score){ return -1;// 如果當前對象應排在參數(shù)對象之前,則返回小于0的數(shù)字 } else if(this.score<o.score){ return 1;// 如果當前對象應排在參數(shù)對象之后,則返回大于0的數(shù)字 } else{ return 0;// 如果當前對象和參數(shù)對象不分先后,則返回0 } }}
那么我們在這里重寫了compareTo的方法,自己定義了比較的規(guī)則,我們就自己再去寫一個sort的方法,去調(diào)用這個compareTo方法,真正意義上實現(xiàn)對 對象數(shù)組的排序
我們使用冒泡排序法
public static void sort(Comparable[] array){// 這里要注意,雖然接口不能實例化對象,// 但是接口類型的引用變量可以指向它的實現(xiàn)類對象// 這里的實現(xiàn)類對象就是實現(xiàn)了這個接口的對象// 例如Comparable[] comparable = new Student[3];// 所以這里的參數(shù)就可以用Comparable[] array來接收 for (int bound = 0;bound<array.length;bound++){ for (int cur = array.length-1;cur>bound;cur--){ if (array[cur-1].compareTo(array[cur])>0){ //這里就說明順序不符合要求,交換兩個變量的位置 Comparable tmp = array[cur-1]; array[cur-1] = array[cur]; array[cur] = tmp; } } }}
sort方法寫好了,我們寫一個main函數(shù)來測試一下
public static void main(String[] args) { Student[] students = new Student[]{ new Student("A",95), new Student("B",91), new Student("C",97), new Student("D",95), }; System.out.println("sort前:"+Arrays.toString(students)); sort(students); System.out.println("sort后:"+Arrays.toString(students)); }
運行結(jié)果
E:\develop\Java\jdk-11\bin\java.exe "-javaagent:E:\IDEA\IntelliJ IDEA Community Edition 2021.3.2\lib\idea_rt.jar=65257:E:\IDEA\IntelliJ IDEA Community Edition 2021.3.2\bin" -Dfile.encoding=UTF-8 -classpath E:\JAVAcode\gyljava\Interface\out\production\Interface ClassArray.Studentsort前:[Student{name='A', score=95}, Student{name='B', score=91}, Student{name='C', score=97}, Student{name='D', score=95}]sort后:[Student{name='C', score=97}, Student{name='A', score=95}, Student{name='D', score=95}, Student{name='B', score=91}]
那么我們?nèi)绻胍凑彰峙判蚰??也是可以?/p>
import java.util.Arrays;import java.util.Comparator;/** * Created with IntelliJ IDEA. * Description: Hello,I would appreciate your comments~ * User:Gremmie * Date: -04-13 * Destination:利用Comparable的接口實現(xiàn)對 對象數(shù)組 選擇性排序的功能 */class Student implements Comparable<Student>{ public String name; public int age; public Student(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public int compareTo(Student o) { return this.name.compareTo(o.name); }}class AgeComparator implements Comparator<Student> { @Override public int compare(Student o1, Student o2) { return o1.age-o2.age; }}class NameComparator implements Comparator<Student> { @Override public int compare(Student o1, Student o2) { return o1.name.compareTo(o2.name); }}public class TestDemo { public static void main(String[] args) { Student[] students = new Student[3]; students[0] = new Student("zhangsan",19); students[1] = new Student("lisi",8); students[2] = new Student("abc",78); AgeComparator ageComparator = new AgeComparator(); NameComparator nameComparator = new NameComparator(); //這里的方法sort是Array里面自帶的,非常方便, //只需將我們寫好的比較器傳過去就好了 System.out.println("排序前:"+Arrays.toString(students)); Arrays.sort(students,nameComparator); System.out.println("排序后:"+Arrays.toString(students)); Comparable<Student>[] studentComparable =students; } public static void main2(String[] args) { /*Student students1 = new Student("zhangsan",19); Student students2 = new Student("abc",78); if(students2.compareTo(students1) > 0) { System.out.println("fafaa"); }*/ } public static void main1(String[] args) { Student[] students = new Student[3]; students[0] = new Student("zhangsan",19); students[1] = new Student("lisi",8); students[2] = new Student("abc",78); System.out.println("排序前:"+Arrays.toString(students)); Arrays.sort(students); System.out.println("排序后:"+Arrays.toString(students)); }}
其作用如其名,是用來進行克隆的,Clonable是個很有用的接口。
Object類中存在一個clone方法,調(diào)用這個方法可以創(chuàng)建出一個對象,實現(xiàn)“拷貝”。
但是我們想要合法調(diào)用clone方法,就要先實現(xiàn)Clonable接口,
否則就會拋出CloneNotSupportedException異常
/** * Created with IntelliJ IDEA. * Description: Hello,I would appreciate your comments~ * User:Gremmie * Date: -04-13 * Destination:利用Clonable的接口實現(xiàn)clone方法,克隆含對象的對象 */class Money implements Cloneable{ public double money = 19.9; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }}class Person implements Cloneable{ public int id = 1234; public Money m = new Money(); @Override public String toString() { return "Person{" + "id='" + id + '\'' + '}'; } @Override protected Object clone() throws CloneNotSupportedException { Person tmp = (Person) super.clone(); tmp.m = (Money) this.m.clone(); return tmp; //return super.clone(); }}public class TestDemo { public static void main(String[] args) { Object o = new Person(); Object o2 = new Money(); } public static void main1(String[] args) throws CloneNotSupportedException { Person person1 = new Person(); Person person2 = (Person)person1.clone(); System.out.println(person1.m.money); System.out.println(person2.m.money); System.out.println("========================="); person2.m.money = 99.99; System.out.println(person1.m.money); System.out.println(person2.m.money); }}
我們?nèi)绻皇峭ㄟ^clone,那么就只是拷貝了Person的對象,但是Person中的money對象我們并沒有拷貝下來,只是單純拷貝下來一個地址,那么我們在這里就要進行深拷貝,講Money類也接受Clonable接口,這樣在調(diào)用clone方法的時候,money也會進行克隆
關(guān)于“Java的接口使用實例分析”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對“Java的接口使用實例分析”知識都有一定的了解,大家如果還想學習更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。