以下是學習《Practical Java(重點版)》的筆記。
1. java的方法參數傳的都是值,而不是引用,傳的對象其實是地址的值。所謂的java傳引用是錯誤的說法,在C#中才有傳引用的說法。
2. 對不變的數據和對象引用使用final。
1)不變的原生態數據類型設置final,如:
public class Test2 {
public static final int A = 3;
public static void main(String[] args) {
Test2.A = 4;//報錯,常量不能夠再重新設置
}
}
2)對對象引用設置final,如:
public class Test2 {
public static final A a = new A();
public static void main(String[] args) {
a.x = 10;
System.out.println(a.x);
a.x = 12;
System.out.println(a.x);
}
}
class A {
int x;
public A() {
}
}
此時A對象中的x值是改變了。
public class Test2 {
public static final A a = new A();
public static void main(String[] args) {
a = new A();//報錯,是因爲a是一個常量對象,不能夠在指向其他對象了。
}
}
總之,如果對對象引用加final的話,是指該引用不能夠再指向其他的對象了,但是指向的對象裏面的值是可以改變的。
3. 在缺省的情況下非private、非靜態方法都可以被子類覆寫。如果想阻止子類覆寫父類方法,可以將父類的方法加final關鍵字。如果子類覆寫了父類的final方法時,在編譯會出現“不能夠覆寫父類的方法”異常。如果將類加final時,這該類沒有子類,編譯會報錯。
4. 對Vectors和arrays要慎重選擇
Java arrays(數組)是一個對象引用,它裏面既可以放原生態類型,也可以放對象。放原生態類型時,有默認值;放對象時,並不會調用類的默認構造方法,而是放的null。Java arrays不能夠超出數組的大小,否則會出現數組越界異常。
Java vector沒有大小限制,當元素被增加或刪除時,其內部元素會移動,以確保大小合適。Java vector只能夠放對象引用,不能夠放基本類型(但從jdk1.5開始有自動裝箱功能,不存在放基本類型問題,因爲基本類型就自動裝箱了)。Vector的底層還是一個array實現。
array 和Vector 的比較
|
支持基本類型 |
支持對象引用 |
自動改變大小 |
速度 |
Array |
Y |
Y |
N |
Y |
Vector |
N |
Y |
Y |
N |
5. 多態(polymorphism)優於instanceof。在java中使用instanceof是爲了在運行期間期確定[某個對象隸屬哪個class]。在多數情況下,可以使用polymorphism避免使用instanceof,這樣可以提供程序的面向對象純度,使程序擴展較好。
1) 如果必須使用instanceof來判斷使用哪個子類的時候,請考慮是否將其接口是否可以增加一個方法,達到通用的目的。
2) 當看到instanceof的時候,請考慮設計上的問題,儘量避免使用它。
6. 必要時才使用instanceof
爲了避免轉型異常,可以使用以下方法:
1.使用try/catch,處理ClassCastExceptio
2. 使用instanceof
7. 一旦不需要對象引用時,就設置爲null。Java垃圾回收機制負責回收不再使用的內存。即使垃圾回收器執行起來,也並非所有[不再被引用](unreferenced)的內存都可被回收。通過[查詢可用內存、調用System.gc()、再查詢可用內存]的步驟,你可以推測你的JVM 所用的垃圾回收器的某些行爲:
Runtime r = Runtime.getRuntime();
long freeM = r.freeMemory();
System.out.println(freeM);
System.gc();
freeM = r.freeMemory();
System.out.println(freeM);
當程序調用System.gc()時,絕大多數JVM 實現品的響應都是執行垃圾回收器。此外,如果內存可用量過低,或CPU 在一段時間內處於空閒狀態時,大多數JVM 也會隱式(自動地)調用垃圾回收器。多長久的空閒纔會引發垃圾回收器被調用呢?這取決於JVM 所採用的垃圾回收算法.
檢閱代碼時,請注意大塊頭對象,尤其是那些存在於完整(或大部分)程序生命中的對象。你應該仔細研究這些對象的建立和運用,以及它們可能引用多少內存。如果它們引用了大量內存,請確定是否所有那些內存在對象生命期內都真的被需要。也許某些大塊頭對象可以解甲歸田,從而使其後執行的代碼能夠更高效地運行任何時刻你都可以通過system.gc()要求垃圾回收器起身行動。如果想將一個對象解除引用(unreference),則可以通過調用System.gc()要求垃圾回收器立刻運轉,在代碼繼續執行前先回收被解除引用的那塊內存。但是你應當仔細考量這種做法爲你的程序性能帶來的潛在影響許多垃圾回收算法會在它們運轉之前先虛懸(suspend)其他所有線程 (threads)這種做法可以確保一旦垃圾回收器開始運轉,就能夠擁有heap 的完整訪問權,可以安全完成任務而不受其他線程的威脅。一旦垃圾回收器完成了任務,便恢復(resume)此前被虛懸的所有線程。因此,通過System.gc()顯示調用,要求垃圾回收器起而運行,你得冒[因執行回收工作而帶來延遲]的風險,延遲程序取決於JVM 所採用的垃圾回收算法。