
[TOC]
第一章:面向?qū)ο?概述
1.1-什么是面向?qū)ο螅?/h3>
概述
- 面向?qū)ο笫且环N程序設(shè)計(jì)思想。
- 程序設(shè)計(jì)的目的是為了用編程解決現(xiàn)實(shí)問題,而面向?qū)ο缶幊痰年P(guān)鍵在于強(qiáng)調(diào)對(duì)象,用什么對(duì)象來完成什么功能。
- 在面向?qū)ο蟪绦蛟O(shè)計(jì)思想中,任何的事物都可以看作對(duì)象,也就是我們經(jīng)常所說的“萬物皆對(duì)象”(一部手機(jī)、一個(gè)人、一條狗等等都可以看做是對(duì)象)。
- 對(duì)象是由屬性和方法組成的。
- 屬性:對(duì)象的狀態(tài)。
- 方法:對(duì)象的行為或功能。
-
圖解對(duì)象(比如:一個(gè)人)
面向?qū)ο缶幊趟枷?/strong>
概述
- 屬性:對(duì)象的狀態(tài)。
- 方法:對(duì)象的行為或功能。
-
圖解對(duì)象(比如:一個(gè)人)
面向?qū)ο缶幊趟枷?/strong>
? 面向?qū)ο缶幊趟枷刖褪?,將真?shí)世界的復(fù)雜關(guān)系,抽象為一個(gè)個(gè)對(duì)象,然后由對(duì)象之間的分工與合作,完成對(duì)真實(shí)世界的模擬。(總而言之,就是找對(duì)象做事兒)
- 真實(shí)世界的復(fù)雜關(guān)系:
明確需求 - 抽象為一個(gè)個(gè)對(duì)象:
劃分對(duì)象 - 對(duì)象之間的分工與合作:
- 分工:
對(duì)象的功能 - 合作:
對(duì)象之間的關(guān)系
- 分工:

面向?qū)ο缶幊痰奶攸c(diǎn)
-
封裝:封裝(encapsulation)就是隱藏對(duì)象的屬性和實(shí)現(xiàn)細(xì)節(jié),僅對(duì)外公開接口,控制在程序中屬性的讀取和修改的訪問級(jí)別 。 -
繼承: 繼承( inheritance)指的是 子類與父類的關(guān)系,子類可以繼承父類中的屬性和方法 -
多態(tài): 多態(tài)(Polymorphism)按字面的意思就是“多種狀態(tài)”。在面向?qū)ο笳Z言中,接口的多種不同的實(shí)現(xiàn)方式即為多態(tài)。
關(guān)于對(duì)象的三大特征,后續(xù)會(huì)逐漸展開講解。
1.2-如何創(chuàng)建和使用對(duì)象?
上述講到,要面向?qū)ο缶幊?,就得找?duì)象做事兒。
找對(duì)象的前提,得先有對(duì)象。
現(xiàn)在沒有對(duì)象怎么辦?
那就得先創(chuàng)建對(duì)象,創(chuàng)建對(duì)象的規(guī)則,需要先知道如何定義類
類
- 類class,是對(duì)現(xiàn)實(shí)生活中一類具有共同特征的事物的抽象 。
比如,“狗”,“狗”是類,不是一個(gè)具體的對(duì)象,而是一個(gè)抽象的名稱或概念,泛指世界上“會(huì)汪汪叫”、“對(duì)主人忠誠”、"會(huì)看家護(hù)院"、“愛啃骨頭”、“有四條腿、兩只眼睛、一個(gè)鼻子、兩只耳朵等”具有這一系列特征的物種的稱呼。
所以,類,簡而言之就是一個(gè)抽象的概念;
對(duì)象
- 對(duì)象,具有屬性和方法的一個(gè)具體的實(shí)例。
類與對(duì)象的關(guān)系
- 類是對(duì)象的模板,可以用來描述對(duì)象的屬性和方法。
- 對(duì)象是類的一個(gè)具體實(shí)例。對(duì)象屬于類。

定義類
關(guān)鍵字:
class-
定義格式:
public class 類名 { // 成員變量-描述對(duì)象的屬性 // 成員方法-描述對(duì)象的方法 } -
代碼演示:
/* 定義類 */ public class Dog { // 成員變量 String name; String type; String color; // 成員方法 public void eat(){ System.out.println("我喜歡啃骨頭"); } public void sound(){ System.out.println("汪汪~~~"); } }
注意:類名單詞的首字母要大寫(比如:Dog)
創(chuàng)建和使用對(duì)象
關(guān)鍵字:
new創(chuàng)建格式:
類名 對(duì)象名 = new 類名()-
使用對(duì)象:
- 操作成員變量:
- 獲取:
對(duì)象名.成員變量 - 設(shè)置:
對(duì)象名.成員變量=值
- 獲取:
- 操作成員方法:
- 調(diào)用方法:
對(duì)象名.成員方法()
- 調(diào)用方法:
- 操作成員變量:
-
代碼:
public class DogTest { public static void main(String[] args) { // 創(chuàng)建對(duì)象 Dog wangCai = new Dog(); // 設(shè)置對(duì)象的屬性-成員變量 wangCai.name = "旺財(cái)"; wangCai.color = "黃色"; wangCai.type = "中華田園犬"; // 讀取對(duì)象的屬性 System.out.println("這一條狗的名字:" + wangCai.name); System.out.println("這一條狗狗的毛色:" + wangCai.color); System.out.println("這一條狗狗的種族:" + wangCai.type); // 調(diào)用對(duì)象的方法 wangCai.eat(); wangCai.sound(); } } -
注意:
- 類是引用數(shù)據(jù)類型,而對(duì)象就是具體的數(shù)據(jù)。
- 對(duì)象的命名和變量命名規(guī)則一樣。
1.3-成員變量的默認(rèn)值是什么?
-
默認(rèn)值:
-
代碼:
public class DogTest02 { public static void main(String[] args) { Dog wangCai = new Dog(); // 讀取對(duì)象的屬性 System.out.println("這一條狗的名字:" + wangCai.name); // null System.out.println("這一條狗狗的毛色:" + wangCai.color); // null System.out.println("這一條狗狗的種族:" + wangCai.type); // null } } // 字符串是引用數(shù)據(jù)類型,索引默認(rèn)值是null
1.4-成員變量和局部變量的區(qū)別?
- 成員變量:定義在類中的方法
外的變量。 - 局部變量:定義在類中的方法
內(nèi)的變量。 - 區(qū)別:
- 位置不同
- 成員變量,類中,方法外。
- 局部變量,類中,方法內(nèi)
- 作用范圍不同
- 成員變量,作用范圍-類中。
- 局部變量,作用方法-方法中
- 默認(rèn)值不同
- 成員變量,有默認(rèn)值。
- 局部變量,沒有默認(rèn)值。并且,使用局部變量時(shí),局部變量必須賦值,否則編譯不通過。
- 內(nèi)存位置不同
- 成員變量,堆區(qū)
- 局部變量,棧區(qū)
- 生命周期不同
- 成員變量,隨著對(duì)象的創(chuàng)建而創(chuàng)建,隨著對(duì)象的銷毀而銷毀。
- 局部變量,隨著方法的調(diào)用而創(chuàng)建,隨著方法調(diào)用完畢而銷毀。
- 位置不同
1.5-圖解內(nèi)存中的對(duì)象
一個(gè)對(duì)象創(chuàng)建并為屬性賦值的內(nèi)存圖
-
Person類代碼
public class Person { // 成員變量 String name; int age; // 成員方法 public void eat(){ System.out.println("吃飯"); } } -
PersonTest類代碼
public class PersonTest { public static void main(String[] args) { Person zs = new Person(); zs.name = "張三"; zs.age = 10; } } -
內(nèi)存圖解
-
總結(jié):
- 對(duì)象是引用數(shù)據(jù)類型的數(shù)據(jù)
一個(gè)對(duì)象調(diào)用方法的內(nèi)存圖
Person類代碼-同上
-
PersonTest類代碼
public class PersonTest { public static void main(String[] args) { Person zs = new Person(); zs.name = "張三"; zs.age = 10; // 調(diào)用方法 zs.eat(); } } -
內(nèi)存圖解
-
總結(jié)
- 調(diào)用方法時(shí),方法會(huì)入棧執(zhí)行,執(zhí)行完畢后會(huì)出棧。
兩個(gè)對(duì)象調(diào)用方法的內(nèi)存圖
Person類代碼-同上
-
PersonTest類代碼
public class PersonTest { public static void main(String[] args) { Person zs = new Person(); zs.name = "張三"; zs.age = 10; zs.eat(); Person ls = new Person(); ls.name = "李四"; ls.age = 11; ls.eat(); } } -
內(nèi)存圖解
-
總結(jié)
- new關(guān)鍵字創(chuàng)建對(duì)象時(shí),都會(huì)獨(dú)立開辟空間存放對(duì)象的信息。
- 所有對(duì)象的成員方法都是共享方法區(qū)中的class文件中的方法(節(jié)省內(nèi)存)。
第二章:面向?qū)ο?封裝
2.1-什么是封裝 ?
? 封裝(encapsulation)就是 隱藏對(duì)象的屬性和實(shí)現(xiàn)細(xì)節(jié),僅對(duì)外公開接口,控制在程序中屬性的讀取和修改的訪問級(jí)別 。
? 封裝的可以讓代碼更加健壯且易于維護(hù),提高程序的安全性。
2.2-如何封裝?
-
private關(guān)鍵字修飾成員變量
- private修飾的成員變量,僅能夠在本類中使用。
- 格式:
private 數(shù)據(jù)類型 成員變量名;
-
對(duì)外提供公開的getXXX/setXXX方法操作對(duì)象的屬性。
- this關(guān)鍵字,在方法中表示調(diào)用方法的對(duì)象。
-
代碼:
public class Person { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
2.3-封裝優(yōu)化-構(gòu)造方法
什么是構(gòu)造方法-construction
與類同名的方法
-
方法修飾沒有返回值類型,沒有void。
public class Person{ // 無參構(gòu)造方法 public Person(){ } }
注意:類默認(rèn)有一個(gè)無參的構(gòu)造方法。構(gòu)造方法可重載
構(gòu)造方法的作用
- 創(chuàng)建對(duì)象。
- 創(chuàng)建對(duì)象時(shí),會(huì)默認(rèn)調(diào)用類的無參構(gòu)造方法。
- 初始化對(duì)象的屬性值。
- 可以定義帶參數(shù)構(gòu)造方法初始化對(duì)象屬性
-
代碼:
-
Person類
public class Person { private String name; private int age; // 無參數(shù)構(gòu)造方法 public Person() { } // 有參數(shù)構(gòu)造方法 public Person(String name, int age) { this.name = name; this.age = age; } public void show(){ System.out.println("姓名:" + this.name); System.out.println("年齡:" + this.age); } } -
測試類
public class PersonTest { public static void main(String[] args) { // 【調(diào)用無參構(gòu)造方法】 Person zs = new Person(); zs.name = "張三"; zs.age = 10; zs.show(); // 打印結(jié)果:姓名:張三 年齡:10 // 【調(diào)用有參構(gòu)造方法】 Person ls = new Person("李四",12); ls.show(); // 打印結(jié)果:姓名:李四 年齡:12 } }
-
2.4-JavaBean
? JavaBean 是 Java語言編寫類的一種標(biāo)準(zhǔn)規(guī)范。符合 JavaBean 的類,要求類必須是具體的和公共的,并且具有無參數(shù)的構(gòu)造方法,提供用來操作成員變量的 set 和 get 方法。
public class 類名 {
// 成員變量
// 無參構(gòu)造方法【必須】
// 有參構(gòu)造方法
// get/set方法
// 成員方法
}
第三章:面向?qū)ο?繼承
3.1-繼承概述?
什么是繼承?
繼承是子類和父類的關(guān)系,子類可以使用父類中的成員。
- 父類:也叫基類或超類。
- 子類:也叫派生類
例如:現(xiàn)實(shí)生活中的繼承

注意:
-
Java的繼承是單繼承,但支持多層繼承。
-
所有的類都直接或間接的繼承了Object類
- Object是祖宗類。
-
對(duì)象 instanceof類檢測一個(gè)對(duì)象是否屬于某個(gè)類。返回布爾值,true表示屬于,false表示不屬于。-
Person類
public class Person { } -
PersonTest類
public class PersonTest { public static void main(String[] args) { Person p1 = new Person(); // p1屬于Person類 System.out.println(p1 instanceof Person); // 結(jié)果:true // p1也屬于Object類 System.out.println(p1 instanceof Object); // 結(jié)果:true } }
-
繼承的作用
- 實(shí)現(xiàn)代碼的復(fù)用性。
- 提高代碼的可擴(kuò)展性。
3.2-如何實(shí)現(xiàn)繼承?
關(guān)鍵字:extends
-
格式
public class 子類 extends 父類 { } -
代碼:
-
父類-手機(jī)類
public class Phone { private String name; private int year; public Phone() { } public Phone(String name, int year) { this.name = name; this.year = year; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getYear() { return year; } public void setYear(int year) { this.year = year; } // 打電話功能 public void call(){ System.out.println("打電話"); } // 發(fā)短信 public void sendMessage(){ System.out.println("發(fā)送文字"); } // 手機(jī)信息 public void showInfo(){ System.out.println("手機(jī)名稱:" + this.name); System.out.println("生產(chǎn)年份:" + this.year); } } -
子類-智能手機(jī)類
/*智能手機(jī)類*/ public class IntelligentPhone extends Phone { public IntelligentPhone() { } public IntelligentPhone(String name, int year) { super(name, year); } public void playMusic(){ System.out.println("播放音樂"); } } -
測試類
public class Test { public static void main(String[] args) { IntelligentPhone iphone = new IntelligentPhone("iphone100",2100); iphone.call(); // 打電話 iphone.sendMessage(); // 發(fā)送文字 iphone.playMusic(); // 播放音樂 iphone.showInfo(); // 手機(jī)名稱:iphone100 生產(chǎn)年份:2100 } }
-
-
關(guān)鍵字:
super,在子類中表示父類的引用。- 在子類中調(diào)用父類構(gòu)造方法:
super(參數(shù)列表) - 在子類中調(diào)用父類的非私有的成員變量:
super.成員變量名 - 在子類中調(diào)用父類的非私有的成員方法:
super.成員方法()
- 在子類中調(diào)用父類構(gòu)造方法:
3.3-方法的重寫-override
子類中的方法和父類中的方法重名時(shí)(返回值和參數(shù)列表一致),叫做方法的重載
-
代碼:
父類-同上手機(jī)類
-
子類
public class IntelligentPhone extends Phone { public IntelligentPhone() { } public IntelligentPhone(String name, int year) { super(name, year); } public void playMusic(){ System.out.println("播放音樂"); } @Override // 重寫父類的方法sendMessage public void sendMessage() { // 調(diào)用父類的發(fā)送文字的功能 super.sendMessage(); // 擴(kuò)展發(fā)送圖片 System.out.println("發(fā)送圖片"); } } -
測試類
public class Test { public static void main(String[] args) { IntelligentPhone iphone = new IntelligentPhone("iphone100",2100); iphone.sendMessage(); } } // 結(jié)果: // 發(fā)送文字 // 發(fā)送圖片
3.7-抽象類、抽象方法
抽象類和抽象方法的定義
- 關(guān)鍵字:
abstract - 抽象方法:只有聲明沒有方法體的方法。
- 格式:
public abstract 返回值類型 方法名(參數(shù)列表); - 一個(gè)抽象方法所在的類,該類一定是抽象類。
- 抽象方法在子類中必須重寫,除非子類也是抽象類。
- 格式:
- 抽象類:被abstruct關(guān)鍵字修飾的類。
- 格式:
public abstract class 類名{} - 抽象類不能被實(shí)例化(不能通過new關(guān)鍵字調(diào)用)。
- 格式:
什么時(shí)候適合使用抽象方法
當(dāng)不同子類有相同的行為,但又有不同的具體實(shí)現(xiàn)時(shí),此時(shí)父類中定義方法時(shí)僅定義聲明即可。
-
代碼:需求-創(chuàng)建一條狗對(duì)象和一只貓對(duì)象,它們有不同的叫聲
-
父類-Animal
public abstract class Animal { private String name; private int age; public Animal() {}; public Animal(String name, int age) { this.name = name; this.age = age; } public void sleep(){ System.out.println("睡覺~~~"); } // 【抽象方法】不同的動(dòng)物,叫聲,所以讓子類重寫具體的方法體 public abstract void shout(); public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } -
子類-Cat
public class Cat extends Animal { public Cat(){} public Cat(String name,int age){ super(name,age); } @Override public void shout() { System.out.println(this.getName() + ":喵喵~~~"); } } -
子類-Dog
public class Dog extends Animal { public Dog(){}; public Dog(String name,int age){ super(name,age); } @Override public void shout() { System.out.println(this.getName() + ":汪汪~~~"); } } -
測試類-Test
public class Test { public static void main(String[] args) { Cat cat = new Cat("湯姆",2); cat.shout(); //結(jié)果: 湯姆:喵喵~~ Dog dog = new Dog("旺財(cái)",3); dog.shout(); // 結(jié)果: 旺財(cái):汪汪~~ } }
-
3.7-接口
概述
- 接口,是一系列方法的集合。若類封裝了成員變量、成員方法、構(gòu)造方法,而接口主要封裝了方法。
- 接口中可以定義抽象方法(jdk7之前)、默認(rèn)方法和靜態(tài)方法(jdk8)、私有方法(jdk9)以及常量。
- 接口可以被實(shí)現(xiàn)(類似于被繼承),實(shí)現(xiàn)接口的類叫做實(shí)現(xiàn)類(類似于子類)。
- 接口中的抽象方法,實(shí)現(xiàn)接口的類必須重寫。否則,實(shí)現(xiàn)類必須是抽象類。
- 類可以實(shí)現(xiàn)多個(gè)接口。
- 接口之間可以實(shí)現(xiàn)多繼承。
接口的定義和實(shí)現(xiàn)
-
格式:
-
定義接口
public interface 接口名稱{ // 【抽象方法】 public abstract 返回?cái)?shù)據(jù)類型 抽象方法名(參數(shù)列表); // 可簡寫為: 返回?cái)?shù)據(jù)類型 抽象方法名(參數(shù)列表); // 【默認(rèn)方法】 public default 返回?cái)?shù)據(jù)類型 方法名(){ // 方法體 } // 【靜態(tài)方法】 public static 返回?cái)?shù)據(jù)類型 方法名(){ // 方法體 } // 【私有方法】 private 返回?cái)?shù)據(jù)類型 方法名(){ // 方法體 } } -
實(shí)現(xiàn)接口:
public class 實(shí)現(xiàn)類名 implements 接口1,接口2...接口n { // 重寫接口中的抽象方法【必須】 // 重寫接口中的默認(rèn)方法【可選】 } -
接口可以繼承其他接口
public interface 接口1 extends 接口2,接口3...接口n{ } -
注意:
- 抽象方法,實(shí)現(xiàn)類必須重寫
- 默認(rèn)方法,實(shí)現(xiàn)類可以繼承,也可以重寫(可選)
- 靜態(tài)方法,實(shí)現(xiàn)類和實(shí)現(xiàn)類的實(shí)例無法調(diào)用。接口名可以調(diào)用。
- 常量,實(shí)現(xiàn)類可以繼承。
- 私有方法,實(shí)現(xiàn)類無法繼承。
-
-
代碼:
-
接口
public interface CommonInterface { // 常量 public final double VERSION = 1.0; // 抽象方法 public abstract void fly(); // 默認(rèn)方法 public default void fn(){ fn1(); System.out.println("默認(rèn)方法"); } // 私有方法 private void fn1(){ System.out.println("私有方法"); } // 靜態(tài)方法 public static void show(){ System.out.println("靜態(tài)方法"); } } -
實(shí)現(xiàn)類
public class Bird implements CommonInterface { @Override public void fly() { System.out.println("展開翅膀飛行"); } } -
測試類
public class Test { public static void main(String[] args) { Bird xn = new Bird(); xn.fly(); xn.fn(); } }
-
接口和抽象類的區(qū)別?
-
相同點(diǎn):
- 都可以定義抽象方法。
- 都可以實(shí)現(xiàn)多態(tài)(第四章)。
- 都不可以被實(shí)例化。
-
不同點(diǎn):
- 接口中不可定義成員變量、構(gòu)造方法、成員方法,抽象類可以。
- 接口可以多被多實(shí)現(xiàn)(類似多繼承)。抽象類僅支持單繼承。
- 接口可以多繼承其他接口。抽象類僅支持單繼承。
什么場景下用繼承類?什么場景下用實(shí)現(xiàn)接口?
-
若強(qiáng)調(diào)多個(gè)類是什么時(shí),可以使用繼承。
-
若強(qiáng)調(diào)多個(gè)類能做什么時(shí),可以使用實(shí)現(xiàn)接口。
第四章:面向?qū)ο?多態(tài)
4.1-什么是多態(tài)?
多態(tài)Polymorphism,按字面意思就是“多種狀態(tài)”。
在面向?qū)ο笳Z言中,接口的多種不同的實(shí)現(xiàn)方式即為多態(tài) 。
多態(tài)性是允許你將父對(duì)象設(shè)置成為一個(gè)或更多的他的子對(duì)象相等的技術(shù),賦值之后,父對(duì)象就可以根據(jù)當(dāng)前賦值給它的子對(duì)象的特性以不同的方式運(yùn)作(摘自“Delphi4 編程技術(shù)內(nèi)幕”)。
簡單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針。
4.2-多態(tài)的好處?
把不同的子類對(duì)象都當(dāng)作父類來看,可以屏蔽不同子類對(duì)象之間的差異,寫出通用的代碼,做出通用的編程,以適應(yīng)需求的不斷變化。
4.3-如何實(shí)現(xiàn)多態(tài)?
實(shí)現(xiàn)多態(tài)的前提條件
- 繼承或者實(shí)現(xiàn)【二選一】
- 方法的重寫【意義體現(xiàn):不重寫,無意義】
- 父類引用指向子類對(duì)象【格式體現(xiàn)】
實(shí)現(xiàn)方式
格式:
父類或被實(shí)現(xiàn)的接口 變量名 = new 子類或?qū)崿F(xiàn)類()-
代碼:
-
父類-Animal
public abstract class Animal { private String name; private String type; public Animal(){} public Animal(String name,String type){ this.name = name; this.type = type; } public abstract void sound(); public String getName() { return name; } public void setName(String name) { this.name = name; } public String getType() { return type; } public void setType(String type) { this.type = type; } } -
子類-Bird
public class Bird extends Animal { public Bird(){} public Bird(String name,String type) { super(name,type); } @Override public void sound() { System.out.println(this.getName() + ":嘰嘰喳喳~~"); } } -
子類-Dog
public class Dog extends Animal { public Dog(){} public Dog(String name,String type) { super(name,type); } @Override public void sound() { System.out.println(this.getName() + ":汪汪~~~"); } public void play(){ System.out.println("狗狗跳起來接飛盤!"); } } -
測試類-Test
public class Test { public static void main(String[] args) { AnimalSound(new Dog("旺財(cái)","中華田園犬")); // 旺財(cái):汪汪~~~ AnimalSound(new Bird("小咕","麻雀")); // 小咕:嘰嘰喳喳~~ } // 動(dòng)物的叫聲 public static void AnimalSound(Animal animal){ animal.sound(); } }
-
4.4-向上向下轉(zhuǎn)型
還是上述代碼,若讓一個(gè)Dog對(duì)象指向父類的引用,再調(diào)用Dog的play方法時(shí),會(huì)編譯出錯(cuò)!
-
代碼
public class Test2 { public static void main(String[] args) { Animal animal = new Dog("旺財(cái)","中華田園犬"); // animal.play(); // 編譯不通過 } }
此時(shí)我們可以通過向下轉(zhuǎn)型為Dog對(duì)象,實(shí)現(xiàn)對(duì)象Dog對(duì)象獨(dú)有的方法調(diào)用。
- 向上轉(zhuǎn)型:
父類/接口 父類引用 = new 子類/實(shí)現(xiàn)類() - 向下轉(zhuǎn)型:
(子類或?qū)崿F(xiàn)類)父類引用
代碼如下:
public class Test2 {
public static void main(String[] args) {
Animal animal = new Dog("旺財(cái)","中華田園犬"); // 向上轉(zhuǎn)型
((Dog) animal).play(); // 狗狗跳起來接飛盤! // 向下轉(zhuǎn)型
}
}
-
注意:
向下轉(zhuǎn)型時(shí),若子類不對(duì)應(yīng),在運(yùn)行時(shí),會(huì)出現(xiàn)ClassCastException異常!
-
可以通過instanceOf方法檢測。
public class Test2 { public static void main(String[] args) { Animal animal = new Bird("小咕","麻雀"); // ((Dog) animal).play(); // ClassCastException 因?yàn)橄蛏限D(zhuǎn)型的子類對(duì)象不是Dog //【正確方式,先驗(yàn)證類型,再調(diào)用】 if(animal instanceof Dog){ ((Dog) animal).play(); } } }
第五章:面向?qū)ο?其他
5.1-final關(guān)鍵字
若定義在父類中的某些成員變量或成員方法,不希望被子類修改,如何操作呢?
可以使用關(guān)鍵字final修飾
- 成員變量
- 被final修飾的成員變量必須初始化,否則編譯不通過。
- 被final修飾的成員變量不能重復(fù)賦值。
- 局部變量
- 被final修飾的局部變量,若不賦值而使用會(huì)編譯不通過。
- 成員方法
- 被final修飾的成員方法,不能被重寫。
- 成員類
- 被final修飾的類,不能被繼承。
5.2-權(quán)限修飾符
概述
在Java中提供了四種訪問權(quán)限,使用不同的訪問權(quán)限修飾符修飾時(shí),被修飾的內(nèi)容會(huì)有不同的訪問權(quán)限,
- public:公共的。
- protected:受保護(hù)的
- default:默認(rèn)的
- private:私有的
不同權(quán)限的訪問能力

可見,public具有最大權(quán)限。private則是最小權(quán)限。
編寫代碼時(shí),如果沒有特殊的考慮,建議這樣使用權(quán)限:
- 成員變量使用 private ,隱藏細(xì)節(jié)。
- 構(gòu)造方法使用 public ,方便創(chuàng)建對(duì)象。
- 成員方法使用 public ,方便調(diào)用方法。
5.3-內(nèi)部類
概述
內(nèi)部類和外部類:將一個(gè)類A定義在另一個(gè)類B里面,里面的那個(gè)類A就稱為內(nèi)部類,B則稱為外部類。
內(nèi)部類定義格式
class 外部類 {
class 內(nèi)部類{ }
}
在描述事物時(shí),若一個(gè)事物內(nèi)部還包含其他事物,就可以使用內(nèi)部類這種結(jié)構(gòu)。比如,汽車類 Car 中包含發(fā)動(dòng)機(jī)
類 Engine ,這時(shí), Engine 就可以使用內(nèi)部類來描述,定義在成員位置。
class Car {
//外部類
class Engine {
//內(nèi)部類
}
}
訪問特點(diǎn)
- 內(nèi)部類可以直接訪問外部類的成員,包括私有成員。
- 外部類要訪問內(nèi)部類的成員,必須要建立內(nèi)部類的對(duì)象。
創(chuàng)建內(nèi)部類對(duì)象
格式:外部類名.內(nèi)部類名 對(duì)象名 = new 外部類型().new 內(nèi)部類型();
-
人類
public class Person { private boolean live = true; class Heart { public void jump() { // 直接訪問外部類成員 if (live) { System.out.println("心臟在跳動(dòng)"); } else { System.out.println("心臟不跳了"); } } } public boolean isLive() { return live; } public void setLive(boolean live) { this.live = live; } } -
測試類
public class Test03 { public static void main(String[] args) { // 創(chuàng)建外部類對(duì)象 Person p = new Person(); // 創(chuàng)建內(nèi)部類對(duì)象 Heart heart = p.new Heart(); // 調(diào)用內(nèi)部類方法 heart.jump(); // 調(diào)用外部類方法 p.setLive(false); // 調(diào)用內(nèi)部類方法 heart.jump(); } } // 輸出結(jié)果: 心臟在跳動(dòng) 心臟不跳了
內(nèi)部類仍然是一個(gè)獨(dú)立的類,在編譯之后會(huì)內(nèi)部類會(huì)被編譯成獨(dú)立的.class文件,但是前面冠以外部類的類名
和$符號(hào) 。 比如,Person$Heart.class
匿名內(nèi)部類介紹
匿名內(nèi)部類 :是內(nèi)部類的簡化寫法。它的本質(zhì)是一個(gè) 帶具體實(shí)現(xiàn)的 父類或者父接口的 匿名的 子類對(duì)象。
開發(fā)中,最常用到的內(nèi)部類就是匿名內(nèi)部類了。以接口舉例,當(dāng)你使用一個(gè)接口時(shí),似乎得做如下幾步操作,
- 定義子類
- 重寫接口中的方法
- 創(chuàng)建子類對(duì)象
- 調(diào)用重寫后的方法
我們的目的,最終只是為了調(diào)用方法,那么能不能簡化一下,把以上四步合成一步呢?匿名內(nèi)部類就是做這樣的快
捷方式。
匿名內(nèi)部類的使用
前提:匿名內(nèi)部類必須繼承一個(gè)父類或者實(shí)現(xiàn)一個(gè)父接口。
-
格式
new 父類名或者接口名(){ // 方法重寫 @Override public void method() { // 執(zhí)行語句 } }; -
代碼
-
Fly接口
public interface Fly { void fly(); } -
測試類
public class Test { public static void main(String[] args) { /* 1.等號(hào)右邊:是匿名內(nèi)部類,定義并創(chuàng)建該接口的子類對(duì)象 2.等號(hào)左邊:是多態(tài)賦值,接口類型引用指向子類對(duì)象 */ Fly bird = new Fly() { @Override public void fly() { System.out.println("小鳥飛..."); } }; // 調(diào)用匿名內(nèi)部類重寫后的方法。 bird.fly(); } }
-
匿名內(nèi)部類的作用
- 是實(shí)現(xiàn)函數(shù)式編程的基礎(chǔ)
5.4-static關(guān)鍵字
概述
關(guān)于 static 關(guān)鍵字的使用,它可以用來修飾的成員變量和成員方法,被修飾的成員是屬于類的,而不是單單是屬
于某個(gè)對(duì)象的。也就是說,既然屬于類,就可以不靠創(chuàng)建對(duì)象來調(diào)用了。
類變量
當(dāng) static 修飾成員變量時(shí),該變量稱為類變量。該類的每個(gè)對(duì)象都共享同一個(gè)類變量的值。任何對(duì)象都可以更改
該類變量的值,但也可以在不創(chuàng)建該類的對(duì)象的情況下對(duì)類變量進(jìn)行操作。
- 定義格式:
修飾符 static 數(shù)據(jù)類型 變量名; - 舉例:
修飾符 static int age
靜態(tài)方法
當(dāng) static 修飾成員方法時(shí),該方法稱為類方法 。靜態(tài)方法在聲明中有 static ,建議使用類名來調(diào)用,而不需要
創(chuàng)建類的對(duì)象。調(diào)用方式非常簡單。
定義格式:
static 返回值類型 方法名(參數(shù)列表){}-
代碼:
public static void show(){ System.out.println("hello"); }
注意事項(xiàng):
- 靜態(tài)方法可以直接訪問類變量和靜態(tài)方法。
- 靜態(tài)方法不能直接訪問普通成員變量或成員方法。反之,成員方法可以直接訪問類變量或靜態(tài)方法。
- 靜態(tài)方法中,不能使用this關(guān)鍵字。
靜態(tài)代碼塊
- 位置:類中方法外
- 格式:
static{} - 執(zhí)行:隨著類的加載而執(zhí)行且執(zhí)行一次,優(yōu)先于main方法和構(gòu)造方法的執(zhí)行。
- 作用:給類變量進(jìn)行初始化賦值
public class ClassName{
static {
// 執(zhí)行語句
}
}
總結(jié)
static 關(guān)鍵字,可以修飾變量、方法和代碼塊。在使用的過程中,其主要目的還是想在不創(chuàng)建對(duì)象的情況
下,去調(diào)用方法。下







