一、接口
1.1 接口的概述
接口是功能的集合,同樣可看做是一種數(shù)據(jù)類型,是比抽象類更為抽象的類 。
接口只描述所應(yīng)該具備的方法,并沒(méi)有具體實(shí)現(xiàn),具體的實(shí)現(xiàn)由接口的實(shí)現(xiàn)類(相當(dāng)于接口的子類)來(lái)完成。這樣將功能的定義與實(shí)現(xiàn)分離,優(yōu)化了程序設(shè)計(jì)。
1.2 接口的格式&使用
1.2.1 接口的格式
與定義類的 class 不同,接口定義時(shí)需要使用 interface 關(guān)鍵字。
定義接口所在的仍為 .java 文件,雖然聲明時(shí)使用的為 interface 關(guān)鍵字的編譯后仍然會(huì)產(chǎn)生 .class 文件。這點(diǎn)可以讓我們將接口看做是一種只包含了功能聲明的特殊類。
定義格式:
public interface 接口名 { 抽象方法1; 抽象方法2; 抽象方法3; }
1.2.2 接口的使用
接口中的方法全是抽象方法,直接 new 接口來(lái)調(diào)用方法沒(méi)有意義,Java也不允許這樣干。
類與接口的關(guān)系為實(shí)現(xiàn)關(guān)系,即類實(shí)現(xiàn)接口。實(shí)現(xiàn)的動(dòng)作類似繼承,只是關(guān)鍵字不同,實(shí)現(xiàn)使用 implements。
其他類(實(shí)現(xiàn)類)實(shí)現(xiàn)接口后,就相當(dāng)于聲明: 我應(yīng)該具備這個(gè)接口中的功能。實(shí)現(xiàn)類仍然需要重寫方法以實(shí)現(xiàn)具體的功能。
格式:
class 類 implements 接口 { 重寫接口中方法 }
在類實(shí)現(xiàn)接口后,該類就會(huì)將接口中的抽象方法繼承過(guò)來(lái),此時(shí)該類需要重寫該抽象方法,完成具體的邏輯。
1.2.3 案例代碼一
實(shí)例
/* * Java語(yǔ)言的繼承是單一繼承,一個(gè)子類只能有一個(gè)父類(一個(gè)兒子只能有一個(gè)親爹) * Java語(yǔ)言給我們提供了一種機(jī)制,用于處理繼承單一的局限性的,接口 * * 接口:接口是一個(gè)比抽象類還抽象的類,接口里所有的方法全是抽象方法,接口和類的關(guān)系是實(shí)現(xiàn),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 接口中成員的特點(diǎn)
-
1、接口中可以定義變量,但是變量必須有固定的修飾符修飾,public static final 所以接口中的變量也稱之為常量,其值不能改變。后面我們會(huì)講解fnal關(guān)鍵字
-
2、接口中可以定義方法,方法也有固定的修飾符,public abstract
-
3、接口不可以創(chuàng)建對(duì)象。
-
4、子類必須覆蓋掉接口中所有的抽象方法后,子類才可以實(shí)例化。否則子類是一個(gè)抽象類。
1.3.1 案例代碼二
實(shí)例
/* * 接口的成員特點(diǎn): * 只能有抽象方法 * 只能有常量 * 默認(rèn)使用public&abstract修飾方法 * 只能使用public&abstract修飾方法 * 默認(rèn)使用public static final來(lái)修飾成員變量 * * 建議:建議大家手動(dòng)的給上默認(rèn)修飾符 * * 注意: * 接口不能創(chuàng)建對(duì)象(不能實(shí)例化) * 類與接口的關(guān)系是實(shí)現(xiàn)關(guān)系,一個(gè)類實(shí)現(xiàn)一個(gè)接口必須實(shí)現(xiàn)它所有的方法 */ 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 接口和類的關(guān)系
- A:類與類之間: 繼承關(guān)系,一個(gè)類只能直接繼承一個(gè)父類,但是支持多重繼承
- B:類與接口之間: 只有實(shí)現(xiàn)關(guān)系,一個(gè)類可以實(shí)現(xiàn)多個(gè)接口
- C:接口與接口之間: 只有繼承關(guān)系,一個(gè)接口可以繼承多個(gè)接口
1.4.1 案例代碼三
實(shí)例
/* * * 類與類:繼承關(guān)系,單一繼承,多層繼承 * 類與接口:實(shí)現(xiàn)關(guān)系,多實(shí)現(xiàn) * 接口與接口的關(guān)系:繼承關(guān)系,多繼承 */ 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 接口的思想
前面學(xué)習(xí)了接口的代碼體現(xiàn),現(xiàn)在來(lái)學(xué)習(xí)接口的思想,接下里從生活中的例子進(jìn)行說(shuō)明。
舉例:我們都知道電腦上留有很多個(gè)插口,而這些插口可以插入相應(yīng)的設(shè)備,這些設(shè)備為什么能插在上面呢?主要原因是這些設(shè)備在生產(chǎn)的時(shí)候符合了這個(gè)插口的使用規(guī)則,否則將無(wú)法插入接口中,更無(wú)法使用。發(fā)現(xiàn)這個(gè)插口的出現(xiàn)讓我們使用更多的設(shè)備。
接口的出現(xiàn)方便后期使用和維護(hù),一方是在使用接口(如電腦),一方在實(shí)現(xiàn)接口(插在插口上的設(shè)備)。例如:筆記本使用這個(gè)規(guī)則(接口),電腦外圍設(shè)備實(shí)現(xiàn)這個(gè)規(guī)則(接口)。
集合體系中大量使用接口:
Collection 接口 List 接口 ArrayList 實(shí)現(xiàn)類 LinkedList 實(shí)現(xiàn)類 Set 接口
1.6 接口優(yōu)點(diǎn)
- 1.類與接口的關(guān)系,實(shí)現(xiàn)關(guān)系,而且是多實(shí)現(xiàn),一個(gè)類可以實(shí)現(xiàn)多個(gè)接口,類與類之間是繼承關(guān)系,java 中的繼承是單一繼承,一個(gè)類只能有一個(gè)父類,打破了繼承的局限性。
- 2.對(duì)外提供規(guī)則(USB接口)
- 3.降低了程序的耦合性(可以實(shí)現(xiàn)模塊化開(kāi)發(fā),定義好規(guī)則,每個(gè)人實(shí)現(xiàn)自己的模塊,提高了開(kāi)發(fā)的效率)
1.7 接口和抽象類的區(qū)別
1.共性:不斷的進(jìn)行抽取,抽取出抽象的,沒(méi)有具體實(shí)現(xiàn)的方法,都不能實(shí)例化(不能創(chuàng)建對(duì)象)
2.區(qū)別
1: 與類的關(guān)系
(1)類與接口是實(shí)現(xiàn)關(guān)系,而且是多實(shí)現(xiàn),一個(gè)類可以實(shí)現(xiàn)多個(gè)接口,類與抽象類是繼承關(guān)系,Java中的繼承是單一繼承,多層繼承,一個(gè)類只能繼承一個(gè)父類,但是可以有爺爺類
(2)區(qū)別2: 成員
a.成員變量 抽象類可以有成員變量,也可以有常量 接口只能有常量,默認(rèn)修飾符public static final b.成員方法 抽象類可以有抽象方法,也可以有非抽象方法 接口只能有抽象方法,默認(rèn)修飾符 public abstract c.構(gòu)造方法 抽象類有構(gòu)造方法,為子類提供 接口沒(méi)有構(gòu)造方法
1.8 運(yùn)動(dòng)員案例

1.8.1 案例代碼四
實(shí)例
/* * 籃球運(yùn)動(dòng)員和教練 乒乓球運(yùn)動(dòng)員和教練 現(xiàn)在籃球運(yùn)動(dòng)員和教練要出國(guó)訪問(wèn),需要學(xué)習(xí)英語(yǔ) 請(qǐng)根據(jù)你所學(xué)的知識(shí),分析出來(lái)哪些是類,哪些是抽象類,哪些是接口 */ public class InterfaceTest { public static void main(String[] args) { //創(chuàng)建籃球運(yùn)動(dòng)員對(duì)象 BasketBallPlayer bbp = new BasketBallPlayer(); bbp.name = "女兆月日"; bbp.age = 35; bbp.gender = "男"; bbp.sleep(); bbp.study(); bbp.speak(); System.out.println("————-"); //創(chuàng)建乒乓球教練對(duì)象 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;//性別 //無(wú)參構(gòu)造 public Person() {} //有參構(gòu)造 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("睡覺(jué)"); } } //學(xué)習(xí)說(shuō)英語(yǔ) interface SpeakEnglish { public abstract void speak(); } //運(yùn)動(dòng)員 abstract class Player extends Person { //學(xué)習(xí) public abstract void study(); } //教練 abstract class Coach extends Person { //教 public abstract void teach(); } //籃球運(yùn)動(dòng)員 class BasketBallPlayer extends Player implements SpeakEnglish{ @Override public void study() { System.out.println("學(xué)扣籃"); } @Override public void speak() { System.out.println("說(shuō)英語(yǔ)"); } } //乒乓球運(yùn)動(dòng)員 class PingpangPlayer extends Player { @Override public void study() { System.out.println("學(xué)抽球"); } } //籃球教練 class BasketBallCoach extends Coach implements SpeakEnglish { @Override public void teach() { System.out.println("教扣籃"); } @Override public void speak() { System.out.println("說(shuō)英語(yǔ)"); } } //乒乓球教練 class PingpangCoach extends Coach { @Override public void teach() { System.out.println("教抽球"); } }
二、多態(tài)
2.1 多態(tài)概述
多態(tài)是繼封裝、繼承之后,面向?qū)ο蟮牡谌筇匦浴?/p>
現(xiàn)實(shí)事物經(jīng)常會(huì)體現(xiàn)出多種形態(tài),如學(xué)生,學(xué)生是人的一種,則一個(gè)具體的同學(xué)張三既是學(xué)生也是人,即出現(xiàn)兩種形態(tài)。
Java 作為面向?qū)ο蟮恼Z(yǔ)言,同樣可以描述一個(gè)事物的多種形態(tài)。如 Student 類繼承了 Person 類,一個(gè) Student 的對(duì)象便既是 Student,又是 Person。
2.2 多態(tài)的定義與使用格式
多態(tài)的定義格式:及時(shí)就是父類的引用變量指向子類對(duì)象
父類類型 變量名 = new 子類類型(); 變量名.方法名();
A:普通類多態(tài)定義的格式
父類 變量名 = new 子類();
如:
class Fu {} class Zi extends Fu {} //類的多態(tài)使用 Fu f = new Zi();
B:抽象類多態(tài)定義的格式
抽象類 變量名 = new 抽象類子類();
如:
abstract class Fu { public abstract void method(); } class Zi extends Fu { public void method(){ System.out.println(“重寫父類抽象方法”); } } //類的多態(tài)使用 Fu fu= new Zi();
C:接口多態(tài)定義的格式
接口 變量名 = new 接口實(shí)現(xiàn)類();
如:
interface Fu { public abstract void method(); } class Zi implements Fu { public void method(){ System.out.println(“重寫接口抽象方法”); } } //接口的多態(tài)使用 Fu fu = new Zi();
2.2.1 案例代碼
實(shí)例
/* * 多態(tài)的前提: * 子父類的繼承關(guān)系 * 方法的重寫 * 父類引用指向子類對(duì)象 * * 動(dòng)態(tài)綁定:運(yùn)行期間調(diào)用的方法,是根據(jù)其具體的類型 * * * * */ public class PoymorphicDemo { public static void main(String[] args) { /*Cat c = new Cat(); c.eat();*/ //父類引用 Animal a //指向 = //子類對(duì)象 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("貓吃魚(yú)"); } }
2.3 多態(tài)成員的特點(diǎn)
A:多態(tài)成員變量
當(dāng)子父類中出現(xiàn)同名的成員變量時(shí),多態(tài)調(diào)用該變量時(shí):
- 編譯時(shí)期:參考的是引用型變量所屬的類中是否有被調(diào)用的成員變量。沒(méi)有,編譯失敗。
- 運(yùn)行時(shí)期:也是調(diào)用引用型變量所屬的類中的成員變量。
簡(jiǎn)單記:編譯和運(yùn)行都參考等號(hào)的左邊。編譯運(yùn)行看左邊。
B:多態(tài)成員方法
- 編譯時(shí)期:參考引用變量所屬的類,如果沒(méi)有類中沒(méi)有調(diào)用的方法,編譯失敗。
- 運(yùn)行時(shí)期:參考引用變量所指的對(duì)象所屬的類,并運(yùn)行對(duì)象所屬類中的成員方法。
簡(jiǎn)而言之:編譯看左邊,運(yùn)行看右邊
2.3.1 案例代碼六
實(shí)例
/* * * 多態(tài)的成員特點(diǎn): * 成員變量 編譯時(shí)看的是左邊,運(yùn)行時(shí)看的左邊 * 成員方法 編譯時(shí)看的是左邊,運(yùn)行時(shí)看右邊 * 靜態(tài)方法 編譯時(shí)看的是左邊,運(yùn)行時(shí)看的也是左邊 * * * 編譯時(shí)看的都是左邊,運(yùn)行時(shí)成員方法看的是右邊,其他(成員變量和靜態(tài)的方法)看的都是左邊 * */ public class PoymorphicDemo2 { public static void main(String[] args) { Dad d = new Kid(); //System.out.println(d.num); //d.method(); d.function();//使用變量去調(diào)用靜態(tài)方法,其實(shí)相當(dāng)于用變量類型的類名去調(diào)用 } } class Dad { int num = 20; public void method() { System.out.println("我是父類方法"); } public static void function() { System.out.println("我是父類靜態(tài)方法"); } } class Kid extends Dad { int num = 10; public void method() { System.out.println("我是子類方法"); } public static void function() { System.out.println("我是子類靜態(tài)方法"); } }
2.4 多態(tài)中向上轉(zhuǎn)型與向下轉(zhuǎn)型
多態(tài)的轉(zhuǎn)型分為向上轉(zhuǎn)型與向下轉(zhuǎn)型兩種:
A:向上轉(zhuǎn)型:當(dāng)有子類對(duì)象賦值給一個(gè)父類引用時(shí),便是向上轉(zhuǎn)型,多態(tài)本身就是向上轉(zhuǎn)型的過(guò)程。
使用格式:
父類類型 變量名 = new 子類類型();
如:
Person p = new Student();
B:向下轉(zhuǎn)型:一個(gè)已經(jīng)向上轉(zhuǎn)型的子類對(duì)象可以使用強(qiáng)制類型轉(zhuǎn)換的格式,將父類引用轉(zhuǎn)為子類引用,這個(gè)過(guò)程是向下轉(zhuǎn)型。如果是直接創(chuàng)建父類對(duì)象,是無(wú)法向下轉(zhuǎn)型的
使用格式:
子類類型 變量名 = (子類類型) 父類類型的變量;
如:
Student stu = (Student) p; // 變量p 實(shí)際上指向 Student 對(duì)象
實(shí)例
/* * * 多態(tài)中的向上轉(zhuǎn)型和向下轉(zhuǎn)型: * * 引用類型之間的轉(zhuǎn)換 * 向上轉(zhuǎn)型 * 由小到大(子類型轉(zhuǎn)換成父類型) * 向下轉(zhuǎn)型 * 由大到小 * 基本數(shù)據(jù)類型的轉(zhuǎn)換 * 自動(dòng)類型轉(zhuǎn)換 * 由小到大 * byte short char — int — long — float — double * 強(qiáng)制類型轉(zhuǎn)換 * 由大到小 * * * */ public class PoymorphicDemo3 { public static void main(String[] args) { Animal2 a = new Dog();//向上轉(zhuǎn)型 //a.eat(); Dog d = (Dog)a;//向下轉(zhuǎn)型 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 多態(tài)的優(yōu)缺點(diǎn)
實(shí)例
/* * * 多態(tài)的優(yōu)缺點(diǎn) * 優(yōu)點(diǎn):可以提高可維護(hù)性(多態(tài)前提所保證的),提高代碼的可擴(kuò)展性 缺點(diǎn):無(wú)法直接訪問(wèn)子類特有的成員 */ 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("紅米打電話"); } }
原文地址:https://www.cnblogs.com/yoke/p/7453864.html