一、Java中的對象基礎(中)

一、面向對象特徵之二:繼承性(Inheritance)

1、爲什麼要有繼承?

	多個類中存在相同屬性和行爲時,將這些內容抽取到單獨一個類中,那麼多個類無需再定義這些屬性和行爲,
只要繼承那個類即可。
	此處的多個類稱爲子類(派生類),單獨的這個類稱爲父類(基類 或超類)。可以理解爲:“子類 is a 父類”。

2、類繼承語法規則

class Subclass extends SuperClass{ }

3、繼承的作用

1. 繼承的出現減少了代碼冗餘,提高了代碼的複用性;
2. 繼承的出現,更有利於功能的擴展;
3. 繼承的出現讓類與類之間產生了關係,提供了多態的前提;
4. 注意:不要僅爲了獲取其他類中某個功能而去繼承。

4、繼承的說明

1. 子類繼承了父類,就繼承了父類的方法和屬性;
2. 在子類中,可以使用父類中定義的方法和屬性,也可以創建新的屬性和方法;
3. 在Java 中,繼承的關鍵字用的是“extends”,即子類不是父類的子集,而是對父類的“擴展”。

5、關於繼承的規則

子類不能直接訪問父類中私有的(private)的成員變量和方法。

6、Java只支持單繼承和多層繼承,不允許多重繼承

1. 一個子類只能有一個父類;
2. 一個父類可以派生出多個子類
	class SubDemo extends Demo{ } //ok
	class SubDemo extends Demo1,Demo2...//error

二、方法的重寫(Override/Overwrite)

定義:在子類中可以根據需要對從父類中繼承來的方法進行改造,也稱爲方法的重置、覆蓋。在程序執行時,
	 子類的方法將覆蓋父類的方法。

要求:
	1. 子類重寫的方法必須和父類被重寫的方法具有相同的方法名稱、參數列表;
	2. 子類重寫的方法的返回值類型不能大於父類被重寫的方法的返回值類型;
	3. 子類重寫的方法使用的訪問權限不能小於父類被重寫的方法的訪問權限,子類不能重寫父類中聲明爲
	private權限的方法;
	5. 子類方法拋出的異常不能大於父類被重寫方法的異常。

注意:
		子類與父類中同名同參數的方法必須同時聲明爲非static的(即爲重寫),或者同時聲明爲static的(不是重寫)。
	因爲static方法是屬於類的,子類無法覆蓋父類的方法。

三、四種訪問權限修飾符

Java權限修飾符public、protected、 (缺省)、 private置於類的成員定義前,用來限定對象對該類成員的訪問權限。

在這裏插入圖片描述

對於class的權限修飾只可以用public和default(缺省)。 
	public類可以在任意地方被訪問。
	default類只可以被同一個包內部的類訪問。

四、關鍵字:super

在Java類中使用super來調用父類中的指定操作:

1. super可用於訪問父類中定義的屬性;
2. super可用於調用父類中定義的成員方法;
3. super可用於在子類構造器中調用父類的構造器。

注意事項:

1. 尤其當子父類出現同名成員時,可以用super表明調用的是父類中的成員;
2. super的追溯不僅限於直接父類;
3. super和this的用法相像,this代表本類對象的引用,super代表父類的內存空間的標識。

調用父類的構造器

1. 子類中所有的構造器默認都會訪問父類中無參數的構造器;
2. 當父類中沒有無參數的構造器時,子類的構造器必須通過this(參數列表)或者super(參數列表)語句指定調用
本類或者父類中相應的構造器。同時,只能”二選一”,且必須放在構造器的首行;
3. 如果子類構造器中既未顯式調用父類或本類的構造器,且父類中又沒有無參的構造器,則編譯出錯。

this和super的區別
在這裏插入圖片描述

五、子類對象的實例化過程

在這裏插入圖片描述

六、面向對象特徵之三:多態性

1. 多態性,是面向對象中最重要的概念,在Java中的體現:

對象的多態性:父類的引用指向子類的對象
	可以直接應用在抽象類和接口上

2. Java引用變量有兩個類型:編譯時類型和運行時類型。

編譯時類型:由聲明該變量時使用的類型決定;
運行時類型:由實際賦給該變量的對象決定。
簡稱:編譯時,看左邊;運行時,看右邊。
	a). 若編譯時類型和運行時類型不一致,就出現了對象的多態性(Polymorphism)
	b). 多態情況下,“看左邊”:看的是父類的引用(父類中不具備子類特有的方法)
				   “看右邊”:看的是子類的對象(實際運行的是子類重寫父類的方法)

3. 對象的多態 —在Java中,子類的對象可以替代父類的對象使用

a). 一個變量只能有一種確定的數據類型。
b). 一個引用類型變量可能指向(引用)多種不同類型的對象。
	Person p = new Student();
	Object o = new Person();  // Object類型的變量o,指向Person類型的對象
	o = new Student();   // Object類型的變量o,指向Student類型的對象

注:子類可看做是特殊的父類,所以父類類型的引用可以指向子類的對象:向上轉型(upcasting)。

4. 一個引用類型變量如果聲明爲父類的類型,但實際引用的是子類對象,那麼該變量就不能再訪問子類中

添加的屬性和方法
	Student m = new Student();
	m.school = “pku”;   // 合法,Student類有school成員變量
	Person e = new Student(); 
	e.school = “pku”;    //  非法,Person類沒有school成員變量
	說明原因:屬性是在編譯時確定的,編譯時e爲Person類型,沒有school成員變量,因而編譯錯誤。

5. 方法聲明的形參類型爲父類類型,可以使用子類的對象作爲實參調用該方法

public class Test {
	public void method(Person e) {
		// ……
		e.getInfo();
	}
	public static void main(Stirng args[]) {
		Test t = new Test();
		Student m = new Student();
		t.method(m);   // 子類的對象m傳送給父類類型的參數e 
	}
}

6. 虛擬方法調用(Virtual Method Invocation)

正常的方法調用

Person e = new Person();
e.getInfo();
Student e = new Student();
e.getInfo();

虛擬方法調用(多態情況下)

	子類中定義了與父類同名同參數的方法,在多態情況下,將此時父類的方法稱爲虛擬方法,父類根據
賦給它的不同子類對象,動態調用屬於子類的該方法。這樣的方法調用在編譯期是無法確定的。
	Person e = new Student();
	e.getInfo();    // 調用Student類的getInfo()方法

編譯時類型和運行時類型

編譯時e爲Person類型,而方法的調用是在運行時確定的,所以調用的是Student類的getInfo()方法。——動態綁定

七、小結:方法的重載與重寫

從編譯和運行的角度看:

	重載,是指允許存在多個同名方法,而這些方法的參數不同。編譯器根據方法不同的參數表,對同名方法的
名稱做修飾。對於編譯器而言,這些同名方法就成了不同的方法。它們的調用地址在編譯期就綁定了。Java的
重載是可以包括父類和子類的,即子類可以重載父類的同名不同參數的方法。所以,對於重載而言,在方法調
用之前,編譯器就已經確定了所要調用的方法,這稱爲“早綁定”或“靜態綁定”; 
	多態,只有等到方法調用的那一刻,解釋運行器纔會確定所要調用的具體方法,這稱爲“晚綁定”或“動態綁定”。

八、多態小結

多態作用:

提高了代碼的通用性,常稱作接口重用

前提:

需要存在繼承或者實現關係
有方法的重寫

成員方法:

編譯時:要查看引用變量所聲明的類中是否有所調用的方法。
運行時:調用實際new的對象所屬的類中的重寫方法。

成員變量:

不具備多態性,只看引用變量所聲明的類。

九、instanceof 操作符

x instanceof A:檢驗x是否爲類A的對象,返回值爲boolean型

要求x所屬的類與類A必須是子類和父類的關係,否則編譯錯誤。
如果x屬於類A的子類B,x instanceof A值也爲true。
	public class Person extends Object {…}
	public class Student extends Person {…}
	public class Graduate extends Person {…}
	-------------------------------------------------------------------
	public void method1(Person e) {
		if (e instanceof Person) 	    // 處理Person類及其子類對象
		if (e instanceof Student) 	    // 處理Student類及其子類對象
		if (e instanceof Graduate)	    // 處理Graduate類及其子類對象
	}

十、對象類型轉換 (Casting )

基本數據類型的Casting:

自動類型轉換:小的數據類型可以自動轉換成大的數據類型
			如:long g=20; double d=12.0f
強制類型轉換:可以把大的數據類型強制轉換(casting)成小的數據類型
			如:float f=(float)12.0; int a=(int)1200L

對Java對象的強制類型轉換稱爲造型

1. 從子類到父類的類型轉換可以自動進行;
2. 從父類到子類的類型轉換必須通過造型(強制類型轉換)實現;
3. 無繼承關係的引用類型間的轉換是非法的;
4. 在造型前可以使用instanceof操作符測試一個對象的類型。

類型轉換示意圖
在這裏插入圖片描述
子類繼承父類

	若子類重寫了父類方法,就意味着子類裏定義的方法徹底覆蓋了父類裏的同名方法,系統將不可能把父類裏
的方法轉移到子類中。
	對於實例變量則不存在這樣的現象,即使子類裏定義了與父類完全相同的實例變量,這個實例變量依然不可
能覆蓋父類中定義的實例變量。

十一、Object類的使用

1、Object類是所有Java類的根父類

如果在類的聲明中未使用extends關鍵字指明其父類,則默認父類爲java.lang.Object類
	public class Person {
		...
	}
	等價於:
	public class Person extends Object {
		...
	} 
	
	例:
		method(Object obj){…}    // 可以接收任何類作爲其參數
		Person o=new Person();
		method(o);

2、==操作符與equals方法

= =:

基本類型比較值:只要兩個變量的值相等,即爲true。
	int a=5; if(a==6){…}
引用類型比較引用(是否指向同一個對象):只有指向同一個對象時,==才返回true。
	Person p1=new Person();
	Person p2=new Person();
	if (p1==p2){…} 
	用“==”進行比較時,符號兩邊的數據類型必須兼容(可自動轉換的基本數據類型除外),否則編譯出錯。

equals():所有類都繼承了Object,也就獲得了equals()方法,還可以重寫。

只能比較引用類型,其作用與“==”相同,比較是否指向同一個對象。
格式:obj1.equals(obj2) 

特例:當用equals()方法進行比較時,對類File、String、Date及包裝類(Wrapper Class)來說,是比較類型及內容而不考慮引用的是否是同一個對象

原因:在這些類中重寫了Object類的equals()方法。

當自定義使用equals()時,可以重寫。用於比較兩個對象的“內容”是否都相等

3、重寫equals()方法的原則

1. 對稱性:如果x.equals(y)返回是“true”,那麼y.equals(x)也應該返回是“true”;
2. 自反性:x.equals(x)必須返回是“true”;
3. 傳遞性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那麼z.equals(x)也應該返回是“true”;
4. 一致性:如果x.equals(y)返回是“true”,只要x和y內容一直不變,不管你重複x.equals(y)多少次,返回都是“true”;
5. 任何情況下,x.equals(null),永遠返回是“false”; x.equals(和x不同類型的對象)永遠返回是“false”。

4、==和equals的區別

1. "=="既可以比較基本類型也可以比較引用類型。對於基本類型就是比較值,對於引用類型就是比較內存地址;
2. equals的話,它是屬於java.lang.Object類裏面的方法,如果該方法沒有被重寫過默認也是"==";我們可以看到
String等類的equals方法是被重寫過的,而且String類在日常開發中用的比較多,久而久之,形成了equals是比
較值的錯誤觀點;
3. 具體要看自定義類裏有沒有重寫Object的equals方法來判斷;
4. 通常情況下,重寫equals方法,會比較類中的相應屬性是否都相等。

十二、包裝類(Wrapper)的使用

1. 針對八種基本數據類型定義相應的引用類型—包裝類(封裝類)

2. 有了類的特點,就可以調用類中的方法,Java纔是真正的面向對象
在這裏插入圖片描述
3. 基本數據類型包裝成包裝類的實例 —裝箱

通過包裝類的構造器實現:
	int i = 500; Integer t = new Integer(i);
還可以通過字符串參數構造包裝類對象:
	Float f = new Float(“4.56”);
	Long l = new Long(“asdf”); //NumberFormatException

4. 獲得包裝類對象中包裝的基本類型變量 —拆箱

調用包裝類的.xxxValue()方法:
	boolean b = bObj.booleanValue();

5. 字符串轉換成基本數據類型

通過包裝類的構造器實現:
	int i = new Integer(“12”);
通過包裝類的parseXxx(String s)靜態方法:
	Float f = Float.parseFloat(“12.1”);

6. 基本數據類型轉換成字符串

調用字符串重載的valueOf()方法:
	String fstr = String.valueOf(2.34f);
更直接的方式:
	String intStr = 5 + “”

十三、native關鍵的理解

	使用 native 關鍵字說明這個方法是原生函數,也就是這個方法是用 C/C++等非Java 語言實現的,並且被
編譯成了 DLL,由 java 去調用。

爲什麼要用 native 方法

	java 使用起來非常方便,然而有些層次的任務用 java 實現起來不容易,或者我們對程序的效率很在意時,
問題就來了。例如:有時 java 應用需要與 java 外面的環境交互。這是本地方法存在的主要原因,你可以想
想 java 需要與一些底層系統如操作系統或某些硬件交換信息時的情況。本地方法正是這樣一種交流機制:它
爲我們提供了一個非常簡潔的接口,而且我們無需去了解 java 應用之外的繁瑣的細節。

native 聲明的方法

	對於調用者,可以當做和其他 Java 方法一樣使用一個 native method 方法可以返回任何 java 類型,包括
非基本類型,而且同樣可以進行異常控制。
	native method 的存在並不會對其他類調用這些本地方法產生任何影響,實際上調用這些方法的其他類甚至
不知道它所調用的是一個本地方法。JVM 將控制調用本地方法的所有細節。如果一個含有本地方法的類被繼承,
子類會繼承這個本地方法並且可以用 java語言重寫這個方法(如果需要的話)。

十四、垃圾回收機制關鍵點

1. 垃圾回收機制只回收JVM堆內存裏的對象空間;
2. 對其他物理連接,比如數據庫連接、輸入流輸出流、Socket連接無能爲力;
3. 現在的JVM有多種垃圾回收實現算法,表現各異;
4. 垃圾回收發生具有不可預知性,程序無法精確控制垃圾回收機制執行;
5. 可以將對象的引用變量設置爲null,暗示垃圾回收機制可以回收該對象;
6. 程序員可以通過System.gc()或者Runtime.getRuntime().gc()來通知系統進行垃圾回收,會有一些效果,
但是系統是否進行垃圾回收依然不確定;
7. 垃圾回收機制回收任何對象之前,總會先調用它的finalize方法(如果覆蓋該方法,讓一個新的引用變量
重新引用該對象,則會重新激活對象);
8. 永遠不要主動調用某個對象的finalize方法,應該交給垃圾回收機制調用;

對以前的知識回顧,加深基礎知識!
學習來自:北京尚硅谷宋紅康老師—Java核心基礎2019年版
每天進步一點點,也許某一天你也會變得那麼渺小!!!

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