Java 再學習 模糊的知識 (三)

繼承

1. super 不是一個對象的引用,不能將 super 賦給另一個對象變量,它只是一個指示編譯器調用超類方法的特殊關鍵字。
2. 繼承並不僅限於一個層次。由一個公共超類派生出來的所有類的集合被稱爲繼承層次。在繼承層次中,從某個特定的類到其祖先的路徑被稱爲該類的繼承鏈。
3. 一個用來判斷是否應該設計爲繼承關係的簡單規則,就是“is-a”規則,它表明子類的每個對象也是超類的對象。“is-a”規則的另一種表述法是置換法則。它表明程序中出現超類對象的任何地方都可以用子類對象置換。
4. 不允許擴展的類被稱爲 final 類。如果在定義類的時候使用了final 修飾符就表明這個類是 final 類。類中的特定方法也可以被聲明爲 final 。如果這樣做,子類就不能覆蓋這個方法( final 類中的所有方法自動地成爲 final 方法,域不會自動成爲 final 域)。
5. 進行類型轉換的原因:在暫時忽視對象的實際類型之後,使用對象的全部功能。因此,要養成這樣一個良好的程序設計習慣:在進行類型轉換之前,先查看一下是否能夠成功地轉換。這個過程簡單地使用 instanceof 運算符就可以實現。
//只能在繼承層次內進行類型轉換
//在將超類轉換爲子類之前,應該使用 instanceof 進行檢查
//在一般情況下,應該儘量少用類型轉換和 instanceof 運算符
if (staffs[0] instanceof Manager) {
	Manager manager2 = (Manager) staffs[0];
	System.out.println(manager2.getBonus());
}
6. 抽象類不能被實例化。但可以定義一個抽象類的對象變量,但是它只能引用非抽象子類的對象。
7. Java 語言規範要求 equals() 方法具有的特性:
  • 自反性: 非空引用 x,x.equals(x) 爲 true;
  • 對稱性: 引用 x,y,若 x.equals(y) 爲 true 則 y.equals(x) 也爲 true;
  • 傳遞性: 引用 x,y,z,若 x.equals(y) 爲 true ,y.equals(z) 爲 true ,則 x.equals(z) 也爲 true ;
  • 一致性: 如果 x 和 y 引用的對象沒有發生變化,反覆調用 x.equals(y) 應該返回同樣的結果;
  • 對於任意非空引用 x ,x.equals(null) 應該返回 false 。
8. 編寫一個完美的 equals() 方法的建議:

1)顯式參數命名爲 otherObject ,稍後需要將它轉換成另一個叫做 other 的變量;
2)檢測 this 與 otherObject 是否引用同一個對象:if ( this == otherObject ) return true; 這條語句只是一個優化。實際上,這是一種經常採用的形式。因爲計算這個等式要比一個一個地比較類中的域所付出的代價小得多。
3)檢測 otherObject 是否爲null ,如果爲 null ,返回 false 。這項檢測是很必要的。if (other0bject = null) return false;
4)比較 this 與 otherObject 是否屬於同一個類。如果 equals 的語義在每個子類中有所改變,就使用 getClass 檢測:if (getClass() != otherobject.getClass() ) return false; 如果所有的子類都擁有統一的語義,就使用 instanceof 檢測:if (!(otherObject instanceof ClassName)) return false;
5)將 otherObject 轉換爲相應的類類型變量:ClassName other = (ClassName) other0bject;
6)現在開始對所有需要比較的域進行比較了。使用 == 比較基本類型域,使用 equals 比
較對象域。如果所有的域都匹配,就返回true;否則返回false。
return field1 == other. field1
&& 0bjects. equals(field2, other. field2)

如果在子類中重新定義 equals ,就要在其中包含調用 super. equals(other)

9. 有關 hashCode 的幾個知識點:
  • 散列碼 (hashcode) 是由對象導出的一個整型值。是沒有規律的。如果 x 和 y 是兩個不同的對象,x.hashCode( ) 與 y.hashCode( ) 基本上不會相同。
  • 字符串的散列碼是由內容導出的。
//hashCodeDisplay
//2225373   2225373
//80223657   2225373
public static void hashCodeDisplay() {
	String a = "Good";
	String b = "Good";
	System.out.println(a.hashCode()+"   "+b.hashCode());
	a = "Study";
	System.out.println(a.hashCode()+"   "+b.hashCode());
}
  • Object 類的默認 hashCode 方法導出的是對象存儲地址
  • 如果重新定義 equals 方法,就必須重新定義 hashCode 方法,以便用戶可以將對象插入到散列表中。equals 與 hashCode 的定義必須一致:如果 x.equals(y) 返回true,那麼 x.hashCode( ) 就必須與 y.hashCode( ) 具有相同的值。例如,如果用定義的Employee.equals 比較僱員的 ID ,那麼 hashCode 方法就需要散列 ID ,而不是僱員的姓名或存儲地址。
  • 需要組合多個散列值時,可以調用 Objects.hash 並提供多個參數,這個方法會對各個參數調用 Objects.hashCode ,並組合這些散列值。
10. 有關 toString() 的幾個知識點:
  • 通過調用 getClass( ).getName( ) 獲得類名的字符串,而不要將類名硬加到 toString 方法中。
  • 隨處可見 toString 方法的主要原因是:只要對象與一個字符串通過操作符“+”連接起來,Java 編譯就會自動地調用 toString 方法,以便獲得這個對象的字符串描述。在調用 x.toString( ) 的地方可以用 “”+x 替代。這條語句將一個空串與 x 的字符串表示相連接。這裏的 x 就是x.totring()。與 toString 不同的是,如果 x 是基本類型,這條語句照樣能夠執行。
11. 一旦能夠確認數組列表(ArrayList)的大小不再發生變化,就可以調用 trimToSize 方法。這個方法將存儲區域的大小調整爲當前元素數量所需要的存儲空間數目。垃圾回收器將回收多餘的存儲空間。一旦整理了數組列表的大小,添加新元素就需要花時間再次移動存儲塊,所以應該在確認不會添加任何元素時,再調用 trimToSize。
12. 裝箱和拆箱是編譯器認可的,而不是虛擬機。編譯器在生成類的字節碼時,插入必要的方法調用。虛擬機只是執行這些字節碼。
13. 參數數量可變的方法
//Nicholas is a Java Programmer.
//He is a greenhand.
public static void main(String[] args) {
	//parameter variable method
	sentenceDisplay("Nicholas ","is ","a ","Java ","Programmer.");
	sentenceDisplay("He ","is ","a ","greenhand.");
}

//parameter variable method
public static void sentenceDisplay(String...args) {
	StringBuilder sb = new StringBuilder();
	for (String string : args) {
		sb.append(string);
	}
	System.out.println(sb.toString());
}
14. 枚舉類及其常用方法

enum

15. 繼承設計的技巧:
  • 將公共操作和域放在超類
  • 不要使用受保護的域(非絕對)
  • 使用繼承實現 “is-a” 關係
  • 除非所有繼承的方法都有意義,否則不要使用繼承
  • 在覆蓋方法時,不要改變預期的行爲
  • 使用多態,而非類型信息
  • 不要過多地使用反射

學習整理自《Java 核心技術 卷一 基礎知識》

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