一. 繼承
- 面向?qū)ο笕筇卣鳎悍庋b楼眷、繼承敞葛、多態(tài)
- 繼承是多態(tài)的前提:沒有繼承坏逢,就沒有多態(tài)
- 繼承主要解決的問題:共性抽取
- 繼承的體現(xiàn):
extends
淤袜、implements
- 子類擁有父類的內(nèi)容,也擁有自己專有的內(nèi)容稚铣;子類也可以當作一個父類
- 代碼中的格式:
- 父類的定義:一個普通的類定義
- 子類的定義:
public class 子類名稱 extends 父類名稱{}
1. 對成員變量的影響
父類和子類的成員變量重名時箱叁,有兩種訪問方式:
-
直接通過子類對象訪問成員變量
- 等號左邊是誰,就優(yōu)先用誰榛泛,沒有則向上找
-
間接通過成員方法訪問成員變量
- 方法屬于誰蝌蹂,就優(yōu)先用誰
區(qū)分局部變量噩斟、父類成員變量曹锨、本類成員變量重名的方法:
this
、super
關(guān)鍵字局部變量:
直接寫變量名
本類的成員變量:
this.成員變量名
父類的成員變量名:
super.成員變量名
2. 對成員方法的影響
成員方法重名:
在繼承關(guān)系中剃允,方法的名稱一樣沛简,參數(shù)列表也一樣-----------重寫(Override)、也叫覆蓋
創(chuàng)建的是子類對象斥废,則優(yōu)先使用子類的方法
方法覆蓋注意事項:
IDEA中寫上
@Override
注解可以來檢測是否是方法覆蓋--------安全檢測手段(推薦)子類方法的返回值必須小于等于父類方法的返回值范圍
子類方法的權(quán)限必須大于等于父類方法的權(quán)限修飾符椒楣。
public
>protected
>(default)
>private
注:defualt
不是關(guān)鍵字,表示留空
3. 對構(gòu)造方法的影響
繼承關(guān)系時牡肉,父子類構(gòu)造方法的訪問特點:
子類必須調(diào)用父類構(gòu)造方法捧灰,不寫則贈送
super()
(子類構(gòu)造方法中默認隱含的super()
調(diào)用)----> 先執(zhí)行父類構(gòu)造方法只有子類構(gòu)造方法,才能調(diào)用父類構(gòu)造方法
子類構(gòu)造可以通過
super
關(guān)鍵字調(diào)用父類重載構(gòu)造方法super
的父類構(gòu)造調(diào)用统锤,必須是子類構(gòu)造方法的第一個語句毛俏,也是唯一一個
4. super關(guān)鍵字典型應(yīng)用
- 在子類的成員方法中,訪問父類的成員變量
- 在子類的成員方法中饲窿,訪問父類的成員方法
- 在子類的構(gòu)造方法中煌寇,訪問父類的構(gòu)造方法
5. this關(guān)鍵字的典型應(yīng)用
- 在本類的成員方法中,訪問本類的成員變量
- 在本類的成員方法中逾雄,訪問本類的另一個成員方法
- 在本類的構(gòu)造方法中阀溶,訪問本類的另一個構(gòu)造方法
-
this(…)
調(diào)用也必須是構(gòu)造方法的第一個語句,也是唯一一個 -
super
和this
兩種構(gòu)造調(diào)用鸦泳,不能同時使用
-
6. super/this內(nèi)存示意圖
7. 繼承的特性
Java中的繼承是單繼承的:一個類的直接父類只能用唯一一個
Java中可以多級繼承
一個父類可以有很多子類
二. 抽象類
抽象方法:父類中不確定具體如何實現(xiàn)的方法-------> 抽象方法
抽象類:包含抽象方法的類-----抽象方法所在的類银锻,必須是抽象類
格式:
-
加上
abstract
關(guān)鍵字,去掉大括號做鹰,沒有方法體public abstract void eat();
如何使用抽象方法击纬、抽象類:
不能直接創(chuàng)建
new
抽象類對象必須用一個子類來繼承抽象父類
子類必須覆蓋重寫(實現(xiàn))抽象類中的所有抽象方法----去掉
abstract
關(guān)鍵字----IDEA中快捷鍵alt+Insert
創(chuàng)建子類對象進行使用
三. 接口
接口就是多個類的公共的規(guī)范標準
接口是一種引用類型,最重要的內(nèi)容就是其中的抽象方法
定義接口的格式:
public interface 接口名稱{
//接口內(nèi)容
}
- 如果是Java 7誊垢,接口內(nèi)容中可以包含:常量掉弛、抽象方法
- 如果是Java 8+症见,還可以額外包含:默認方法、靜態(tài)方法
- 如果是Java 9+殃饿,還可以額外包含:私有方法
- 接口中的抽象方法谋作,修飾符必須是兩個固定的關(guān)鍵字:public abstract
- 這兩個關(guān)鍵字,可以選擇性省略(初學(xué)不推薦)
接口使用步驟:
-
不能直接使用乎芳,必須有一個實現(xiàn)類來實現(xiàn)接口
public class 實現(xiàn)類名稱 implements 接口名{}
接口的實現(xiàn)類必須覆蓋重寫(實現(xiàn))接口中所有的抽象方法
創(chuàng)建實現(xiàn)類的對象遵蚜,進行使用
接口包含--默認方法
- 問題描述:
接口升級問題:接口中新增了一個抽象方法,那么在實現(xiàn)類中就必須要修改去實現(xiàn)新增的抽象方法
- 解決方案:
新添加的方法--->定義成默認方法--->實現(xiàn)類中不用覆蓋重寫
public default 返回值類型 方法名稱(參數(shù)列表){
}
- 接口的默認方法奈惑,可以通過接口實現(xiàn)類對象吭净,直接調(diào)用
- 接口的默認方法,也可以被接口實現(xiàn)類進行覆蓋重寫
接口包含--靜態(tài)方法
public static 返回值類型 方法名稱(參數(shù)列表){
}
- 不能通過接口實現(xiàn)類的對象來調(diào)用接口中的靜態(tài)方法
- 正確方法:通過接口名稱直接調(diào)用接口中的靜態(tài)方法
接口包含--私有方法
- 問題描述:
抽取一個共有方法肴甸,解決兩個默認方法之間重復(fù)代碼的問題寂殉,但是這個公共方法不應(yīng)該讓實現(xiàn)類使用,應(yīng)該是私有化的
解決方案:
-
普通私有化方法:解決多個默認方法之間重復(fù)代碼問題
private 返回值類型 方法名稱(參數(shù)列表){}
-
靜態(tài)私有方法:解決多個靜態(tài)方法之間重復(fù)代碼問題
private static 返回值類型 方法名稱(參數(shù)列表){}
只有接口自己能調(diào)用
接口包含--成員變量
接口中也可以定義“成員變量”原在,但必須使用public static final
三個關(guān)鍵字進行修飾,從效果上看友扰,其實就是接口的【常量】
格式與注意事項:
public static final 數(shù)據(jù)類型 常量名稱 = 數(shù)據(jù)值;
public static final
關(guān)鍵字可以省略不寫接口中的常量,必須進行賦值
推薦:常量名稱完全大寫庶柿,并用下劃線進行分隔-----
NUM_MONEY
注意事項
接口不能有靜態(tài)代碼塊
接口不能用構(gòu)造方法
-
一個類的有且只有一個直接父類村怪,但是一個類可以同時實現(xiàn)多個接口----用逗號隔開
public class Interfaceimpl implements MyInterface1,MyInterface2{}
如果實現(xiàn)類所實現(xiàn)的多個接口類中有重名的抽象方法,則只需要重寫覆蓋一遍
如果實現(xiàn)類所實現(xiàn)的多個接口類中有重名的默認方法浮庐,那么實現(xiàn)類一定要對沖突的默認方法進行覆蓋重寫
一個類的直接父類中的方法和接口當中的默認方法產(chǎn)生了沖突甚负,優(yōu)先使用父類當中的方法
類與接口的關(guān)系
- 類與類之間是單繼承的,直接父類只有一個
- 類與接口之間是多實現(xiàn)的审残,一個類可以實現(xiàn)多個接口梭域、
- 接口與接口之間是多繼承的
四. 多態(tài)
extends
繼承或者implements
實現(xiàn),是多態(tài)性的前提對象的多態(tài)性:一個對象擁有多種形態(tài)
代碼中體現(xiàn)多態(tài)性:
-
父類引用指向子類對象
-
父類名稱 對象名 = new 子類名稱();
左父右子---子類被當作父類來看待(一只貓被當作動物看待) 接口名稱 對象名 = new 實現(xiàn)類名稱();
-
成員變量的訪問規(guī)則
- 直接通過對象名稱訪問:看等號左邊是誰维苔,就優(yōu)先用誰碰辅,沒有則向上(父類)找
- 間接通過成員方法訪問:看該方法屬于誰,就優(yōu)先用誰介时,沒有則向上(父類)找
- 口訣:編譯看左邊没宾,運行還看左邊
成員方法的訪問規(guī)則
- 看
new
的是誰,就優(yōu)先用誰沸柔,沒有則向上(父類)找 - 口訣:編譯看左邊循衰,運行看右邊
ublic class Demo03MultiMethod {
public static void main(String[] args) {
Fu obj = new Zi();
obj.method();//父子都有,優(yōu)先用子
obj.methodFu();//子類沒有褐澎,父類有,向上找父類
//編譯看左邊会钝,左邊是Fu,F(xiàn)u中沒有methodZi()方法,所以編譯報錯
//obj.methodZi();錯誤寫法
}
}
多態(tài)的好處
五. 引用類型轉(zhuǎn)型
多態(tài)的轉(zhuǎn)型分為向上轉(zhuǎn)型和向下轉(zhuǎn)型
對象的向上轉(zhuǎn)型
對象的向上轉(zhuǎn)型迁酸,其實就是多態(tài)寫法
父類名稱 對象名 = new 子類名稱();
子類被當作父類來看待(一只貓被當作動物看待)向上轉(zhuǎn)型一定是安全的:從小范圍轉(zhuǎn)向了大范圍
對象的向下轉(zhuǎn)型
問題描述:
向上轉(zhuǎn)型的弊端---對象一旦向上轉(zhuǎn)型為父類先鱼,就無法調(diào)用子類原本持有的內(nèi)容
對象的向下轉(zhuǎn)型
其實就是一個【還原】的動作
格式:
子類名稱 對象名 = (子類名稱)父類對象;
Animal animal = new Cat();//本來是貓,向上轉(zhuǎn)型為動物
Cat cat = (Cat) animal;//將本來已經(jīng)轉(zhuǎn)型為動物的貓奸鬓,還原成本來的貓
注意事項:
對象創(chuàng)建的時候必須保證本來就是貓
類似于基本數(shù)據(jù)類型的強制轉(zhuǎn)換
六. instanceof關(guān)鍵字
問題描述:
如何知道一個父類引用的對象焙畔,本來是什么子類?(對象本來創(chuàng)建的時候是一只貓呢串远?)
格式:
對象名 instanceof 類名稱
返回一個
boolean
結(jié)果宏多,判斷了前面的對象能不能當作后面類型的實例
七. 多態(tài)-接口的練習(xí)
Usb接口
package cn.arnold.day03.demo04;
public interface Usb {
//開啟usb
public void openUsb();
//關(guān)閉usb
public void closeUsb();
}
鼠標實現(xiàn)類
package cn.arnold.day03.demo04;
public class Mouse implements Usb {
@Override
public void openUsb() {
System.out.println("打開鼠標usb");
}
@Override
public void closeUsb() {
System.out.println("關(guān)閉鼠標usb");
}
//鼠標點擊功能
public void click() {
System.out.println("鼠標點擊");
}
}
鍵盤實現(xiàn)類
package cn.arnold.day03.demo04;
public class KeyBoard implements Usb {
@Override
public void openUsb() {
System.out.println("打開鍵盤usb");
}
@Override
public void closeUsb() {
System.out.println("關(guān)閉鍵盤usb");
}
//鍵盤輸入功能
public void type() {
System.out.println("鍵盤輸入");
}
}
電腦類
package cn.arnold.day03.demo04;
public class KeyBoard implements Usb {
@Override
public void openUsb() {
System.out.println("打開鍵盤usb");
}
@Override
public void closeUsb() {
System.out.println("關(guān)閉鍵盤usb");
}
//鍵盤輸入功能
public void type() {
System.out.println("鍵盤輸入");
}
}
主方法類
package cn.arnold.day03.demo04;
/*
描述筆記本類,實現(xiàn)筆記本使用鼠標澡罚、鍵盤
1.usb接口:包含開啟伸但、關(guān)閉功能
2.筆記本類:包含開機、關(guān)機留搔、使用usb設(shè)備功能
3.鼠標實現(xiàn)類:實現(xiàn)usb接口更胖、鼠標點擊功能
4.鍵盤實現(xiàn)類:實現(xiàn)usb接口、鍵盤輸入功能
*/
public class Main {
public static void main(String[] args) {
Computer com = new Computer();
//開機
com.powerOn();
//使用鼠標usb設(shè)備
Usb usb = new Mouse();//將鼠標向上轉(zhuǎn)型為Usb
com.useUsbDevice(usb);
//使用鍵盤設(shè)備
com.useUsbDevice(new KeyBoard());//使用匿名對象催式,隱藏了keyboard向上轉(zhuǎn)型為Usb操作
/*KeyBoard keyboard = new KeyBoard();
com.useUsbDevice(keyboard);*/
//關(guān)機
com.powerOff();
}
}
八. final關(guān)鍵字
含義:
最終的函喉、不可改變的
修飾一個類
格式:
修飾符 final class 類名稱{}
-
含義:
- 當前這個類不能有任何子類(太監(jiān)類)
- 其中所有的成員方法都無法進行覆蓋重寫(因為沒兒子)
修飾一個方法
- 格式:
修飾符 final 返回值類型 方法名(參數(shù)列表){}
- 含義:不能被覆蓋重寫
注意事項:
- 對于類和方法來說,不能同時使用
abstract
和final
關(guān)鍵字-----互相矛盾
修飾一個局部變量
- 格式:
修飾符 final 變量類型 變量名 = 值
必須賦值 - 含義:一次賦值荣月,終生不變
注意事項:
- 對于基本數(shù)據(jù)類型,不可變的是數(shù)值---------只能賦值一次
- 對于引用數(shù)據(jù)類型梳毙,不可變的是地址值 ----- 只能
new
一次
修飾成員變量
- 格式:
private final 變量類型 變量名
- 含義:變量也是不可變的-----
Setter
方法失效
注意事項:
- 由于成員變量有默認值哺窄,當使用
final
關(guān)鍵字后,編譯器將不再贈送默認值账锹,必須手動賦值 - 要么直接賦值萌业,要么通過構(gòu)造方法賦值(二者選其一)
- 通過構(gòu)造方法賦值必須保證所有重載形式的構(gòu)造方法都對這個變量賦值
九. 權(quán)限修飾符
public | protected | (default)省略不寫 | private | |
---|---|---|---|---|
同一類中 | YES | YES | YES | YES |
同一個包 | YES | YES | YES | NO |
不同包---子類 | YES | YES | NO | NO |
不同包---非子類 | YES | NO | NO | NO |
十. 內(nèi)部類
例如:身體和心臟(內(nèi)部類)的關(guān)系,心臟必須依賴于身體才有用
成員內(nèi)部類
- 格式:
修飾符 class 外部類名稱 {
修飾符 class 內(nèi)部類名稱 {
//...
}
//...
}
使用規(guī)則:
內(nèi)用外奸柬,隨意訪問生年;外用內(nèi),需要內(nèi)部對象
編譯后的
.class
文件信息:Body.class
廓奕、Body$Heart.class
如何使用成員內(nèi)部類:
間接訪問:在外部類的方法中抱婉,使用內(nèi)部類,在main中只是調(diào)用外部類的方法
直接訪問:
外部類名稱.內(nèi)部類名稱 對象名稱 = new 外部類名稱().內(nèi)部類名稱();
桌粉,在main中通過創(chuàng)建的對象內(nèi)部類蒸绩、外部類成員變量重名:
外部類名稱.this.外部類成員變量名
局部內(nèi)部類(包含匿名內(nèi)部類)
一個類定義在一個方法內(nèi)部------局部內(nèi)部類
含義:只有當前所屬的方法才能使用它,出了這個方法就不能用了
格式:
public 返回值 方法名(參數(shù)列表) {
class 內(nèi)部類名稱 {
//...
}
//...
}
注意事項:
局部內(nèi)部類铃肯,如果希望訪問方法的局部變量患亿,那么這個局部變量必須是【有效
final
的】原因:局部類對象(堆)的生命周期比局部變量(棧)長
內(nèi)部類的修飾符規(guī)則
- 外部類:
publi
/(default)
- 成員內(nèi)部類:
public
/protected
/(default)
/private
- 局部內(nèi)部類:
(default)
匿名內(nèi)部類(重點)
問題描述:
如果接口的實現(xiàn)類(或者是父類的子類)只需要使用唯一的一次,這種情況下就可以省略掉該類的定義押逼,改為使用匿名內(nèi)部類
定義格式:直接
new
接口
接口名稱 對象名 = new 接口名稱(){
//覆蓋重寫接口方法----匿名內(nèi)部類
};
注意事項:
接口名稱 對象名 = new 接口名稱(){...};
new代表創(chuàng)建的動作
接口名稱就是匿名內(nèi)部類需要實現(xiàn)的那個接口
{...}
才是匿名內(nèi)部類的內(nèi)容匿名內(nèi)部類步藕,在創(chuàng)建對象的時候惦界,只能使用唯一的一次------需要重復(fù)使用接口方法則不要用匿名內(nèi)部類
匿名對象,在調(diào)用方法的時候咙冗,只能調(diào)用唯一的一次(一次只能調(diào)用一個方法)---
new Student().studyCoding()
十一. 引用類型用法總結(jié)
基本類型可以作為成員變量表锻、作為方法的參數(shù)、作為方法的返回值乞娄,引用類型同樣可以-----String
就是引用類型