接口
1.1 接口的概述
接口是功能的集合,同樣可看做是一種數據類型,是比抽象類更為抽象的”類”。
接口只描述所應該具備的方法,並沒有具體實現,具體的實現由接口的實現類(相當於接口的子類)來完成。這樣將功能的定義與實現分離,優化了程序設計。
1.2 接口的格式&使用
1.2.1 接口的格式
與定義類的class不同,接口定義時需要使用interface關鍵字。
定義接口所在的仍為.java文件,雖然聲明時使用的為interface關鍵字的編譯后仍然會產生.class文件。這點可以讓我們將接口看做是一種只包含了功能聲明的特殊類。
定義格式:
public interface 接口名 { 抽象方法1; 抽象方法2; 抽象方法3; }
1.2.2 接口的使用
接口中的方法全是抽象方法,直接new接口來調用方法沒有意義,Java也不允許這樣干
類與接口的關系為實現關系,即類實現接口。實現的動作類似繼承,只是關鍵字不同,實現使用implements
其他類(實現類)實現接口后,就相當於聲明:”我應該具備這個接口中的功能”。實現類仍然需要重寫方法以實現具體的功能。
格式:
class 類 implements 接口 { 重寫接口中方法 }
在類實現接口后,該類就會將接口中的抽象方法繼承過來,此時該類需要重寫該抽象方法,完成具體的邏輯。
1.2.3 案例代碼一
package com.gao_01; /* * Java語言的繼承是單一繼承,一個子類只能有一個父類(一個兒子只能有一個親爹) * Java語言給我們提供了一種機制,用於處理繼承單一的局限性的,接口 * * 接口:接口是一個比抽象類還抽象的類,接口里所有的方法全是抽象方法,接口和類的關系是實現,implements * interface * * 格式: * interface 接口名 { * * } * */ public class InterfaceDemo { public static void main(String[] args) { BillGates gates = new BillGates(); gates.code(); } } class Boss { public void manage() { System.out.println("管理公司"); } } class Programmer { public void code() { System.out.println("敲代碼"); } } //比爾蓋茨 class BillGates extends Programmer { }
1.3 接口中成員的特點
1、接口中可以定義變量,但是變量必須有固定的修飾符修飾,public static final 所以接口中的變量也稱之為常量,其值不能改變。后面我們會講解fnal關鍵字
2、接口中可以定義方法,方法也有固定的修飾符,public abstract
3、接口不可以創建對象。
4、子類必須覆蓋掉接口中所有的抽象方法后,子類才可以實例化。否則子類是一個抽象類。
1.3.1 案例代碼二
package com.gao_01; /* * 接口的成員特點: * 只能有抽象方法 * 只能有常量 * 默認使用public&abstract修飾方法 * 只能使用public&abstract修飾方法 * 默認使用public static final來修飾成員變量 * * 建議:建議大家手動的給上默認修飾符 * * 注意: * 接口不能創建對象(不能實例化) * 類與接口的關系是實現關系,一個類實現一個接口必須實現它所有的方法 */ public class InterfaceDemo2 { public static void main(String[] args) { //Animal a = new Animal(); //Animal.num; } } interface Animal { public static final int num = 10; public abstract void eat(); } class Cat implements Animal { public void eat() { } }
1.4 接口和類的關系
A:類與類之間:繼承關系,一個類只能直接繼承一個父類,但是支持多重繼承
B:類與接口之間:只有實現關系,一個類可以實現多個接口
C:接口與接口之間:只有繼承關系,一個接口可以繼承多個接口
1.4.1 案例代碼三
package com.gao_01; /* * * 類與類:繼承關系,單一繼承,多層繼承 * 類與接口:實現關系,多實現 * 接口與接口的關系:繼承關系,多繼承 */ public class InterfaceDemo3 { public static void main(String[] args) { } } interface InterA extends InterB { public abstract void method(); } interface InterB { public abstract void function(); } interface InterC extends InterA { } class Demo implements InterC { @Override public void method() { // TODO Auto-generated method stub } @Override public void function() { // TODO Auto-generated method stub } }
1.5 接口的思想
前面學習了接口的代碼體現,現在來學習接口的思想,接下里從生活中的例子進行說明。
舉例:我們都知道電腦上留有很多個插口,而這些插口可以插入相應的設備,這些設備為什么能插在上面呢?主要原因是這些設備在生產的時候符合了這個插口的使用規則,否則將無法插入接口中,更無法使用。發現這個插口的出現讓我們使用更多的設備。
接口的出現方便后期使用和維護,一方是在使用接口(如電腦),一方在實現接口(插在插口上的設備)。例如:筆記本使用這個規則(接口),電腦外圍設備實現這個規則(接口)。
集合體系中大量使用接口
Collection接口
List接口
ArrayList實現類
LinkedList實現類
Set接口
1.6 接口優點
1.類與接口的關系,實現關系,而且是多實現,一個類可以實現多個接口,類與類之間是繼承關系,java中的繼承是單一繼承,一個類只能有一個父類,打破了繼承的局限性。
2.對外提供規則(USB接口)
3.降低了程序的耦合性(可以實現模塊化開發,定義好規則,每個人實現自己的模塊,提高了開發的效率)
1.7 接口和抽象類的區別
1.共性:
不斷的進行抽取,抽取出抽象的,沒有具體實現的方法,都不能實例化(不能創建對象)
2.區別1: 與類的關系
(1)類與接口是實現關系,而且是多實現,一個類可以實現多個接口,類與抽象類是繼承關系,Java中的繼承是單一繼承,多層繼承,一個類只能繼承一個父類,但是可以有爺爺類
(2)區別2: 成員
a.成員變量
抽象類可以有成員變量,也可以有常量
接口只能有常量,默認修飾符public static final
b.成員方法
抽象類可以有抽象方法,也可以有非抽象方法
接口只能有抽象方法,默認修飾符 public abstract
c.構造方法
抽象類有構造方法,為子類提供
接口沒有構造方法
1.8 運動員案例
1.8.1 案例代碼四
package com.gao_02; /* * 籃球運動員和教練 乒乓球運動員和教練 現在籃球運動員和教練要出國訪問,需要學習英語 請根據你所學的知識,分析出來哪些是類,哪些是抽象類,哪些是接口 */ public class InterfaceTest { public static void main(String[] args) { //創建籃球運動員對象 BasketBallPlayer bbp = new BasketBallPlayer(); bbp.name = "女兆月日"; bbp.age = 35; bbp.gender = "男"; bbp.sleep(); bbp.study(); bbp.speak(); System.out.println("-------------"); //創建乒乓球教練對象 PingpangCoach ppc = new PingpangCoach(); ppc.name = "劉胖子"; ppc.age = 40; ppc.gender = "男"; ppc.sleep(); ppc.teach(); //ppc.speak(); } } class Person { String name;//姓名 int age;//年齡 String gender;//性別 //無參構造 public Person() {} //有參構造 public Person(String name,int age,String gender) { this.name = name; this.age = age; this.gender = gender; } //吃 public void eat() { System.out.println("吃飯"); } //睡 public void sleep() { System.out.println("睡覺"); } } //學習說英語 interface SpeakEnglish { public abstract void speak(); } //運動員 abstract class Player extends Person { //學習 public abstract void study(); } //教練 abstract class Coach extends Person { //教 public abstract void teach(); } //籃球運動員 class BasketBallPlayer extends Player implements SpeakEnglish{ @Override public void study() { System.out.println("學扣籃"); } @Override public void speak() { System.out.println("說英語"); } } //乒乓球運動員 class PingpangPlayer extends Player { @Override public void study() { System.out.println("學抽球"); } } //籃球教練 class BasketBallCoach extends Coach implements SpeakEnglish { @Override public void teach() { System.out.println("教扣籃"); } @Override public void speak() { System.out.println("說英語"); } } //乒乓球教練 class PingpangCoach extends Coach { @Override public void teach() { System.out.println("教抽球"); } }
多態
2.1 多態概述
多態是繼封裝、繼承之后,面向對象的第三大特性。
現實事物經常會體現出多種形態,如學生,學生是人的一種,則一個具體的同學張三既是學生也是人,即出現兩種形態。
Java作為面向對象的語言,同樣可以描述一個事物的多種形態。如Student類繼承了Person類,一個Student的對象便既是Student,又是Person。
2.2 多態的定義與使用格式
多態的定義格式:及時就是父類的引用變量指向子類對象
父類類型 變量名 = new 子類類型(); 變量名.方法名();
A:普通類多態定義的格式
父類 變量名 = new 子類(); 如: class Fu {} class Zi extends Fu {} //類的多態使用 Fu f = new Zi();
B:抽象類多態定義的格式
抽象類 變量名 = new 抽象類子類(); 如: abstract class Fu { public abstract void method(); } class Zi extends Fu { public void method(){ System.out.println(“重寫父類抽象方法”); } } //類的多態使用 Fu fu= new Zi();
C:接口多態定義的格式
接口 變量名 = new 接口實現類(); 如: interface Fu { public abstract void method(); } class Zi implements Fu { public void method(){ System.out.println(“重寫接口抽象方法”); } } //接口的多態使用 Fu fu = new Zi();
2.2.1 案例代碼
package com.gao_01; /* * 多態的前提: * 子父類的繼承關系 * 方法的重寫 * 父類引用指向子類對象 * * 動態綁定:運行期間調用的方法,是根據其具體的類型 * * * * */ public class PoymorphicDemo { public static void main(String[] args) { /*Cat c = new Cat(); c.eat();*/ //父類引用 Animal a //指向 = //子類對象 new Cat() Animal a = new Cat(); a.eat(); } } class Animal { public void eat() { System.out.println("吃東西"); } } class Cat extends Animal { public void eat() { System.out.println("貓吃魚"); } }
2.3 多態成員的特點
A:多態成員變量
當子父類中出現同名的成員變量時,多態調用該變量時:
編譯時期:參考的是引用型變量所屬的類中是否有被調用的成員變量。沒有,編譯失敗。
運行時期:也是調用引用型變量所屬的類中的成員變量。
簡單記:編譯和運行都參考等號的左邊。編譯運行看左邊。
B:多態成員方法
編譯時期:參考引用變量所屬的類,如果沒有類中沒有調用的方法,編譯失敗。
運行時期:參考引用變量所指的對象所屬的類,並運行對象所屬類中的成員方法。
簡而言之:編譯看左邊,運行看右邊
2.3.1 案例代碼六
package com.gao_01; /* * * 多態的成員特點: * 成員變量 編譯時看的是左邊,運行時看的左邊 * 成員方法 編譯時看的是左邊,運行時看右邊 * 靜態方法 編譯時看的是左邊,運行時看的也是左邊 * * * 編譯時看的都是左邊,運行時成員方法看的是右邊,其他(成員變量和靜態的方法)看的都是左邊 * */ public class PoymorphicDemo2 { public static void main(String[] args) { Dad d = new Kid(); //System.out.println(d.num); //d.method(); d.function();//使用變量去調用靜態方法,其實相當於用變量類型的類名去調用 } } class Dad { int num = 20; public void method() { System.out.println("我是父類方法"); } public static void function() { System.out.println("我是父類靜態方法"); } } class Kid extends Dad { int num = 10; public void method() { System.out.println("我是子類方法"); } public static void function() { System.out.println("我是子類靜態方法"); } }
2.4 多態中向上轉型與向下轉型
多態的轉型分為向上轉型與向下轉型兩種:
A:向上轉型:當有子類對象賦值給一個父類引用時,便是向上轉型,多態本身就是向上轉型的過程。
使用格式:
父類類型 變量名 = new 子類類型();
如:Person p = new Student();
B:向下轉型:一個已經向上轉型的子類對象可以使用強制類型轉換的格式,將父類引用轉為子類引用,這個過程是向下轉型。如果是直接創建父類對象,是無法向下轉型的
使用格式:
子類類型 變量名 = (子類類型) 父類類型的變量;
如:Student stu = (Student) p; //變量p 實際上指向Student對象
package com.gao_01; /* * * 多態中的向上轉型和向下轉型: * * 引用類型之間的轉換 * 向上轉型 * 由小到大(子類型轉換成父類型) * 向下轉型 * 由大到小 * 基本數據類型的轉換 * 自動類型轉換 * 由小到大 * byte short char --- int --- long --- float --- double * 強制類型轉換 * 由大到小 * * * */ public class PoymorphicDemo3 { public static void main(String[] args) { Animal2 a = new Dog();//向上轉型 //a.eat(); Dog d = (Dog)a;//向下轉型 d.swim(); } } class Animal2 { public void eat() { System.out.println("吃東西"); } } class Dog extends Animal2 { public void eat() { System.out.println("啃骨頭"); } public void swim() { System.out.println("狗刨"); } }
2.5 多態的優缺點
package com.gao_01; /* * * 多態的優缺點 * 優點:可以提高可維護性(多態前提所保證的),提高代碼的可擴展性 缺點:無法直接訪問子類特有的成員 */ public class PoymorphicDemo4 { public static void main(String[] args) { MiFactory factory = new MiFactory(); factory.createPhone(new MiNote()); factory.createPhone(new RedMi()); } } class MiFactory { /*public void createPhone(MiNote mi) { mi.call(); } public void createPhone(RedMi mi) { mi.call(); }*/ public void createPhone(Phone p) { p.call(); } } interface Phone { public void call(); } //小米Note class MiNote implements Phone{ public void call() { System.out.println("小米Note打電話"); } } //紅米 class RedMi implements Phone { public void call() { System.out.println("紅米打電話"); } }