標籤:
隨著電腦革命的發展,“不安全”的編程方式已經逐漸成為編程代價高昂的主因之一。
初始化和清理,正是涉及安全的倆個問題。
5.1 用構造器確保初始化
構造器名與類名相同,沒有傳回值
5.2 方法重載
構造器的重載與方法重載
5.2.1 區分重載的方法
參數列表的不同(不同順序也是重載,但不建議這麼做)
5.2.2 涉及基本類型的重載
void print(char c){System.out.println("The character is "+c); }
void print(byte b){System.out.println("The byte is "+b);}
void print(short s){System.out.println("The short is "+s);}
void print(int i){System.out.println("The int is "+i);}
void print(long l){System.out.println("The long is "+l);}
void print(float f){System.out.println("The float is "+f);}
void print(double d){System.out.println("The double is "+d); }
1)如果直接傳入數值,如 print(5)則5會被當做 int x = 5; print(x)去尋找最合適的print(int)
2)常量之外的類型會去尋找最合適的類型,沒有同類型,但是有更大類型時會型別提升
3)char是一個特例,如果沒有print(char)則char當做int,執行print(int)
4)需要用cast才能放入小類型的方法裡
5.2.3 用傳回值區分重載方法
void f(){}
int f(){return 1;}
這樣是不可以的,因為很多時候我們不需要傳回值,只是調用而已,那麼我們會寫:
f();這樣是無法區分它是哪個方法的
5.3 預設構造器
如果類裡沒有構造器,編譯器會幫你弄一個。
有了就不會幫你造一個了。
5.4 this關鍵字
可以用於指代調用對象方法時的“當前對象”,可以解決參數和域重名問題。
5.4.1 構造器中調用構造器
this(參數);
必須放於第一行,且最多隻能調用一個。
5.4.2 static的含義
static方法就是沒有this的方法,它屬於類,不屬於對象。
5.5 清理:最終處理和記憶體回收
Java記憶體回收行程負責回收由new建立並且不再被使用的對象。
特殊情況是:如果一個對象以非new方式獲得了一塊記憶體地區,GC就不知道怎麼回收這塊特殊的記憶體。Java提供了finalize()方法,它的工作原理“假定”是這樣的:一旦記憶體回收行程準備好釋放對象佔用的儲存空間,將首先調用finalize()方法, 並且在下一次記憶體回收動作發生時,才會真正回收對象記憶體。所以finalize()方法可以在記憶體回收時做一些重要的清理工作。
//此處疑惑感謝@Launcher的細心解答。
//---------------解答開始
也就是你有這樣一個 class,偽碼:
class A{
IntPtr m_pBuffer;
A(){
m_pBuffer = malloc(1000);
}
void finalize(){
free(_M_pBuffer);
}
}
A 對象沒有用 new ,而是使用 malloc 獲得了一塊特殊的記憶體區 m_pBuffer。
A a = new A(); // 還是使用 new 獲得對象 A
但是對象 a 本身不用 new 獲得的特殊記憶體區 m_pBuffer,不會被 GC 釋放,所以你需要實現 finalize,在裡面手動釋放。
//---------------解答結束
這裡有一個誤區:
finalize() 與 C++中的解構函式(銷毀對象時必須要用到這個函數)相同。
這是不正確的,C++中對象一定會被銷毀,即解構函式一定被調用,而Java裡的對象並不總是被記憶體回收。換句話說:
1)對象可能不被記憶體回收
2)記憶體回收不等於析構
5.5.1 finalize()用途何在
3)記憶體回收只與記憶體有關。
Java中無論對象是如何建立的,GC都會回收它的記憶體,對finalize()的需要限制到一種特殊情況:用了建立對象以外的方式,為對象分配了儲存空間。
之所以要有finalize(),是由於在分配記憶體時可能採用了類似C語言的做法,這種情況主要發生在使用Java調用本地代碼,如用C的malloc()函數系列來分配儲存空間,所以需要在finalize()裡調用本地代碼,使用free()來釋放這些記憶體。
所以不要過多使用finalize(),它不是進行普通清理工作的合適場所。
5.5.2 你必須實施清理
C++中所有對象都會被銷毀。包括局部對象(在棧上建立的)和用new建立的對象(delete調用解構函式)。
Java不允許建立局部對象,必須使用new建立,也沒有delete可用,釋放對象記憶體只能由GC來完成,但是它並不保證一定去回收。如果希望在進行釋放儲存空間之外的清理操作,得明確在finalize()裡使用,這等於析構了,但是沒析構方便。
如果JVM沒有面臨記憶體耗盡的情況,它是不會浪費時間和資源去執行記憶體回收以恢複記憶體的。
5.5.3 終結條件
因為finalize()方法是在記憶體回收前執行的,所以複寫finalize方法可以檢測"邏輯上"的這個對象是否應該被終結。藉此來發現程式中是否有缺陷。如:某對象代表了一個開啟著的檔案,而我們規定這種對象回收時必須為關閉狀態。為了檢測程式是否有缺陷,我們可以複寫finalize方法檢測是否開啟狀態,然後在某次finalize中查看是否存在問題,雖然finalize並不一定會調用,但是只要調用了一次我們就知道是否有問題,這才是關鍵。
我們可以利用System.gc()來建議做GC操作,但JVM有可能不聽我們的。
5.5.4 記憶體回收行程如何工作
Java編程思想:第5章 初始化與清理