java基礎九

第一章 接口

1.1 概述
接口,是Java語言中一種引用類型,是方法的集合,如果說類的內部封裝了成員變量、構造方法和成員方法,那麼
接口的內部主要就是封裝了方法,包含抽象方法(JDK 7及以前),默認方法和靜態方法(JDK 8),私有方法
(JDK 9)。
接口的定義,它與定義類方式相似,但是使用 interface 關鍵字。它也會被編譯成.class文件,但一定要明確它並
不是類,而是另外一種引用數據類型。
引用數據類型:數組,類,接口。
接口的使用,它不能創建對象,但是可以被實現( implements ,類似於被繼承)。一個實現接口的類(可以看做
是接口的子類),需要實現接口中所有的抽象方法,創建該類對象,就可以調用方法了,否則它必須是一個抽象
類。
1.2 定義格式
public interface 接口名稱 {
// 抽象方法
// 默認方法
// 靜態方法
// 私有方法
}
含有抽象方法
抽象方法:使用 abstract 關鍵字修飾,可以省略,沒有方法體。該方法供子類實現使用。
代碼如下:
含有默認方法和靜態方法
默認方法:使用 default 修飾,不可省略,供子類調用或者子類重寫。
靜態方法:使用 static 修飾,供接口直接調用。
代碼如下:
含有私有方法和私有靜態方法
私有方法:使用 private 修飾,供接口中的默認方法或者靜態方法調用。
代碼如下:
1.3 基本的實現
實現的概述
類與接口的關係爲實現關係,即類實現接口,該類可以稱爲接口的實現類,也可以稱爲接口的子類。實現的動作類
似繼承,格式相仿,只是關鍵字不同,實現使用 implements 關鍵字。
非抽象子類實現接口:

  1. 必須重寫接口中所有抽象方法。
  2. 繼承了接口的默認方法,即可以直接調用,也可以重寫。
    實現格式:
    public interface InterFaceName {
    public abstract void method();
    } p
    ublic interface InterFaceName {
    public default void method() {
    // 執行語句
    } p
    ublic static void method2() {
    // 執行語句
    }
    } p
    ublic interface InterFaceName {
    private void method() {
    // 執行語句
    }
    }
    抽象方法的使用
    必須全部實現,代碼如下:
    定義接口:
    定義實現類:
    定義測試類:
    默認方法的使用
    可以繼承,可以重寫,二選一,但是隻能通過實現類的對象來調用。
  3. 繼承默認方法,代碼如下:
    class 類名 implements 接口名 {
    // 重寫接口中抽象方法【必須】
    // 重寫接口中默認方法【可選】
    } p
    ublic interface LiveAble {
    // 定義抽象方法
    public abstract void eat();
    public abstract void sleep();
    } p
    ublic class Animal implements LiveAble {
    @Override
    public void eat() {
    System.out.println(“喫東西”);
    } @
    Override
    public void sleep() {
    System.out.println(“晚上睡”);
    }
    } p
    ublic class InterfaceDemo {
    public static void main(String[] args) {
    // 創建子類對象
    Animal a = new Animal();
    // 調用實現後的方法
    a.eat();
    a.sleep();
    }
    } 輸
    出結果:
    喫東西
    晚上睡
    定義接口:
    定義實現類:
    定義測試類:
  4. 重寫默認方法,代碼如下:
    定義接口:
    定義實現類:
    定義測試類:
    public interface LiveAble {
    public default void fly(){
    System.out.println(“天上飛”);
    }
    } p
    ublic class Animal implements LiveAble {
    // 繼承,什麼都不用寫,直接調用
    } p
    ublic class InterfaceDemo {
    public static void main(String[] args) {
    // 創建子類對象
    Animal a = new Animal();
    // 調用默認方法
    a.fly();
    }
    } 輸
    出結果:
    天上飛
    public interface LiveAble {
    public default void fly(){
    System.out.println(“天上飛”);
    }
    } p
    ublic class Animal implements LiveAble {
    @Override
    public void fly() {
    System.out.println(“自由自在的飛”);
    }
    }
    靜態方法的使用
    靜態與.class 文件相關,只能使用接口名調用,不可以通過實現類的類名或者實現類的對象調用,代碼如下:
    定義接口:
    定義實現類:
    定義測試類:
    私有方法的使用
    私有方法:只有默認方法可以調用。
    私有靜態方法:默認方法和靜態方法可以調用。
    如果一個接口中有多個默認方法,並且方法中有重複的內容,那麼可以抽取出來,封裝到私有方法中,供默認方法
    去調用。從設計的角度講,私有的方法是對默認方法和靜態方法的輔助。同學們在已學技術的基礎上,可以自行測
    試。
    定義接口:
    public class InterfaceDemo {
    public static void main(String[] args) {
    // 創建子類對象
    Animal a = new Animal();
    // 調用重寫方法
    a.fly();
    }
    } 輸
    出結果:
    自由自在的飛
    public interface LiveAble {
    public static void run(){
    System.out.println(“跑起來~~~”);
    }
    } p
    ublic class Animal implements LiveAble {
    // 無法重寫靜態方法
    } p
    ublic class InterfaceDemo {
    public static void main(String[] args) {
    // Animal.run(); // 【錯誤】無法繼承方法,也無法調用
    LiveAble.run(); //
    }
    } 輸
    出結果:
    跑起來~~~
    接口的多實現
    之前學過,在繼承體系中,一個類只能繼承一個父類。而對於接口而言,一個類是可以實現多個接口的,這叫做接
    口的多實現。並且,一個類能繼承一個父類,同時實現多個接口。
    實現格式:
    [ ]: 表示可選操作。
    抽象方法
    接口中,有多個抽象方法時,實現類必須重寫所有抽象方法。如果抽象方法有重名的,只需要重寫一次。代碼如
    下:
    定義多個接口:
    定義實現類:
    public interface LiveAble {
    default void func(){
    func1();
    func2();
    } p
    rivate void func1(){
    System.out.println(“跑起來~~~”);
    } p
    rivate void func2(){
    System.out.println(“跑起來~~~”);
    }
    } c
    lass 類名 [extends 父類名] implements 接口名1,接口名2,接口名3… {
    // 重寫接口中抽象方法【必須】
    // 重寫接口中默認方法【不重名時可選】
    } i
    nterface A {
    public abstract void showA();
    public abstract void show();
    } i
    nterface B {
    public abstract void showB();
    public abstract void show();
    } p
    ublic class C implements A,B{
    默認方法
    接口中,有多個默認方法時,實現類都可繼承使用。如果默認方法有重名的,必須重寫一次。代碼如下:
    定義多個接口:
    定義實現類:
    靜態方法
    接口中,存在同名的靜態方法並不會衝突,原因是隻能通過各自接口名訪問靜態方法。
    優先級的問題
    當一個類,既繼承一個父類,又實現若干個接口時,父類中的成員方法與接口中的默認方法重名,子類就近選擇執
    行父類的成員方法。代碼如下:
    定義接口:
    @Override
    public void showA() {
    System.out.println(“showA”);
    } @
    Override
    public void showB() {
    System.out.println(“showB”);
    } @
    Override
    public void show() {
    System.out.println(“show”);
    }
    } i
    nterface A {
    public default void methodA(){}
    public default void method(){}
    } i
    nterface B {
    public default void methodB(){}
    public default void method(){}
    } p
    ublic class C implements A,B{
    @Override
    public void method() {
    System.out.println(“method”);
    }
    }
    定義父類:
    定義子類:
    定義測試類:
    1.5 接口的多繼承【瞭解】
    一個接口能繼承另一個或者多個接口,這和類之間的繼承比較相似。接口的繼承使用 extends 關鍵字,子接口繼
    承父接口的方法。如果父接口中的默認方法有重名的,那麼子接口需要重寫一次。代碼如下:
    定義父接口:
    interface A {
    public default void methodA(){
    System.out.println(“AAAAAAAAAAAA”);
    }
    } c
    lass D {
    public void methodA(){
    System.out.println(“DDDDDDDDDDDD”);
    }
    } c
    lass C extends D implements A {
    // 未重寫methodA方法
    } p
    ublic class Test {
    public static void main(String[] args) {
    C c = new C();
    c.methodA();
    }
    } 輸
    出結果:
    DDDDDDDDDDDD
    定義子接口:
    小貼士:
    子接口重寫默認方法時,default關鍵字可以保留。
    子類重寫默認方法時,default關鍵字不可以保留。

    Java 8中引入了一個新的概念,叫做default方法,也可以稱爲Defender方法,或者虛擬擴展方法(Virtual extension methods)。
    Default方法是指,在接口內部包含了一些默認的方法實現(也就是接口中可以包含方法體,這打破了Java之前版本對接口的語法限制)

    1.6 其他成員特點
    接口中,無法定義成員變量,但是可以定義常量,其值不可以改變,默認使用public static final修飾。
    接口中,沒有構造方法,不能創建對象。
    接口中,沒有靜態代碼塊。

第二章 多態

2.1 概述
引入
多態是繼封裝、繼承之後,面向對象的第三大特性。
生活中,比如跑的動作,小貓、小狗和大象,跑起來是不一樣的。再比如飛的動作,昆蟲、鳥類和飛機,飛起來也
是不一樣的。可見,同一行爲,通過不同的事物,可以體現出來的不同的形態。多態,描述的就是這樣的狀態。
定義
多態: 是指同一行爲,具有多個不同表現形式。
前提【重點】
interface A {
public default void method(){
System.out.println(“AAAAAAAAAAAAAAAAAAA”);
}
} i
nterface B {
public default void method(){
System.out.println(“BBBBBBBBBBBBBBBBBBB”);
}
} i
nterface D extends A,B{
@Override
public default void method() {
System.out.println(“DDDDDDDDDDDDDD”);
}
}
繼承或者實現【二選一】
2. 方法的重寫【意義體現:不重寫,無意義】
3. 父類引用指向子類對象【格式體現】
2.2 多態的體現
多態體現的格式:
父類類型:指子類對象繼承的父類類型,或者實現的父接口類型。
代碼如下:
當使用多態方式調用方法時,首先檢查父類中是否有該方法,如果沒有,則編譯錯誤;如果有,執行的是子類重寫
後方法。
代碼如下:
定義父類:
定義子類:
定義測試類:
父類類型 變量名 = new 子類對象;
變量名.方法名();
Fu f = new Zi();
f.method();
public abstract class Animal {
public abstract void eat();
} c
lass Cat extends Animal {
public void eat() {
System.out.println(“喫魚”);
}
} c
lass Dog extends Animal {
public void eat() {
System.out.println(“喫骨頭”);
}
}
多態的好處
實際開發的過程中,父類類型作爲方法形式參數,傳遞子類對象給方法,進行方法的調用,更能體現出多態的擴展
性與便利。代碼如下:
定義父類:
定義子類:
定義測試類:
public class Test {
public static void main(String[] args) {
// 多態形式,創建對象
Animal a1 = new Cat();
// 調用的是 Cat 的 eat
a1.eat();
// 多態形式,創建對象
Animal a2 = new Dog();
// 調用的是 Dog 的 eat
a2.eat();
}
} p
ublic abstract class Animal {
public abstract void eat();
} c
lass Cat extends Animal {
public void eat() {
System.out.println(“喫魚”);
}
} c
lass Dog extends Animal {
public void eat() {
System.out.println(“喫骨頭”);
}
} p
ublic class Test {
public static void main(String[] args) {
// 多態形式,創建對象
Cat c = new Cat();
Dog d = new Dog();
// 調用showCatEat
showCatEat©;
// 調用showDogEat
由於多態特性的支持,showAnimalEat方法的Animal類型,是Cat和Dog的父類類型,父類類型接收子類對象,當
然可以把Cat對象和Dog對象,傳遞給方法。
當eat方法執行時,多態規定,執行的是子類重寫的方法,那麼效果自然與showCatEat、showDogEat方法一致,
所以showAnimalEat完全可以替代以上兩方法。
不僅僅是替代,在擴展性方面,無論之後再多的子類出現,我們都不需要編寫showXxxEat方法了,直接使用
showAnimalEat都可以完成。
所以,多態的好處,體現在,可以使程序編寫的更簡單,並有良好的擴展。
2.4 引用類型轉換
多態的轉型分爲向上轉型與向下轉型兩種:
向上轉型
向上轉型:多態本身是子類類型向父類類型向上轉換的過程,這個過程是默認的。
當父類引用指向一個子類對象時,便是向上轉型。
使用格式:
向下轉型
向下轉型:父類類型向子類類型向下轉換的過程,這個過程是強制的。
showDogEat(d);
/*
以上兩個方法, 均可以被showAnimalEat(Animal a)方法所替代
而執行效果一致
*/
showAnimalEat©;
showAnimalEat(d);
} p
ublic static void showCatEat (Cat c){
c.eat();
} p
ublic static void showDogEat (Dog d){
d.eat();
} p
ublic static void showAnimalEat (Animal a){
a.eat();
}
} 父
類類型 變量名 = new 子類類型();
如:Animal a = new Cat();
北京市昌平區建材城西路金燕龍辦公樓一層 電話:400-618-9090一個已經向上轉型的子類對象,將父類引用轉爲子類引用,可以使用強制類型轉換的格式,便是向下轉型。
使用格式:
爲什麼要轉型
當使用多態方式調用方法時,首先檢查父類中是否有該方法,如果沒有,則編譯錯誤。也就是說,不能調用子類擁
有,而父類沒有的方法。編譯都錯誤,更別說運行了。這也是多態給我們帶來的一點"小麻煩"。所以,想要調用子
類特有的方法,必須做向下轉型。
轉型演示,代碼如下:
定義類:
定義測試類:
子類類型 變量名 = (子類類型) 父類變量名;
如:Cat c =(Cat) a;
abstract class Animal {
abstract void eat();
} c
lass Cat extends Animal {
public void eat() {
System.out.println(“喫魚”);
} p
ublic void catchMouse() {
System.out.println(“抓老鼠”);
}
} c
lass Dog extends Animal {
public void eat() {
System.out.println(“喫骨頭”);
} p
ublic void watchHouse() {
System.out.println(“看家”);
}
} p
ublic class Test {
public static void main(String[] args) {
// 向上轉型
Animal a = new Cat();
a.eat(); // 調用的是 Cat 的 eat
// 向下轉型
Cat c = (Cat)a;
c.catchMouse(); // 調用的是 Cat 的 catchMouse
}
}
轉型的異常
轉型的過程中,一不小心就會遇到這樣的問題,請看如下代碼:
這段代碼可以通過編譯,但是運行時,卻報出了 ClassCastException ,類型轉換異常!這是因爲,明明創建了
Cat類型對象,運行時,當然不能轉換成Dog對象的。這兩個類型並沒有任何繼承關係,不符合類型轉換的定義。
爲了避免ClassCastException的發生,Java提供了 instanceof 關鍵字,給引用變量做類型的校驗,格式如下:
所以,轉換前,我們最好先做一個判斷,代碼如下:

第三章 接口多態的綜合案例

3.1 筆記本電腦
public class Test {
public static void main(String[] args) {
// 向上轉型
Animal a = new Cat();
a.eat(); // 調用的是 Cat 的 eat
// 向下轉型
Dog d = (Dog)a;
d.watchHouse(); // 調用的是 Dog 的 watchHouse 【運行報錯】
}
} 變
量名 instanceof 數據類型
如果變量屬於該數據類型,返回true。
如果變量不屬於該數據類型,返回false。
public class Test {
public static void main(String[] args) {
// 向上轉型
Animal a = new Cat();
a.eat(); // 調用的是 Cat 的 eat
// 向下轉型
if (a instanceof Cat){
Cat c = (Cat)a;
c.catchMouse(); // 調用的是 Cat 的 catchMouse
} else if (a instanceof Dog){
Dog d = (Dog)a;
d.watchHouse(); // 調用的是 Dog 的 watchHouse
}
}
}
筆記本電腦(laptop)通常具備使用USB設備的功能。在生產時,筆記本都預留了可以插入USB設備的USB接口,
但具體是什麼USB設備,筆記本廠商並不關心,只要符合USB規格的設備都可以。
定義USB接口,具備最基本的開啓功能和關閉功能。鼠標和鍵盤要想能在電腦上使用,那麼鼠標和鍵盤也必須遵守
USB規範,實現USB接口,否則鼠標和鍵盤的生產出來也無法使用。
3.2 案例分析
進行描述筆記本類,實現筆記本使用USB鼠標、USB鍵盤
USB接口,包含開啓功能、關閉功能
筆記本類,包含運行功能、關機功能、使用USB設備功能
鼠標類,要實現USB接口,並具備點擊的方法
鍵盤類,要實現USB接口,具備敲擊的方法
3.3 案例實現
定義USB接口:
定義鼠標類:
定義鍵盤類:
interface USB {
void open();// 開啓功能
void close();// 關閉功能
} c
lass Mouse implements USB {
public void open() {
System.out.println(“鼠標開啓,紅燈閃一閃”);
} p
ublic void close() {
System.out.println(“鼠標關閉,紅燈熄滅”);
} p
ublic void click(){
System.out.println(“鼠標單擊”);
}
}
定義筆記本類:
測試類,代碼如下:
class KeyBoard implements USB {
public void open() {
System.out.println(“鍵盤開啓,綠燈閃一閃”);
} p
ublic void close() {
System.out.println(“鍵盤關閉,綠燈熄滅”);
} p
ublic void type(){
System.out.println(“鍵盤打字”);
}
} c
lass Laptop {
// 筆記本開啓運行功能
public void run() {
System.out.println(“筆記本運行”);
} /
/ 筆記本使用usb設備,這時當筆記本對象調用這個功能時,必須給其傳遞一個符合USB規則的USB設備
public void useUSB(USB usb) {
// 判斷是否有USB設備
if (usb != null) {
usb.open();
// 類型轉換,調用特有方法
if(usb instanceof Mouse){
Mouse m = (Mouse)usb;
m.click();
}else if (usb instanceof KeyBoard){
KeyBoard kb = (KeyBoard)usb;
kb.type();
} u
sb.close();
}
} p
ublic void shutDown() {
System.out.println(“筆記本關閉”);
}
} p
ublic class Test {
public static void main(String[] args) {
// 創建筆記本實體對象
Laptop lt = new Laptop();
// 筆記本開啓
lt.run();
// 創建鼠標實體對象
Usb u = new Mouse();
// 筆記本使用鼠標
lt.useUSB(u);
// 創建鍵盤實體對象
KeyBoard kb = new KeyBoard();
// 筆記本使用鍵盤
lt.useUSB(kb);
// 筆記本關閉
lt.shutDown();
}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章