1. 程式人生 > >JAVA程式設計思想學習筆記(四)初始化與清理

JAVA程式設計思想學習筆記(四)初始化與清理

初始化與清理

用構造器確保初始化

JAVA採用和C++相同的方案,即構造器採用與類相同的名稱,在建立物件時,將會為物件分配儲存空間,並呼叫同名的構造器,達到確保初始化的目的。
構造器是一種特殊的方法,它是沒有返回值的,與返回值為空(void)不同。
另外,如果自己沒有實現構造器,就會呼叫預設構造器,但是,如果你建立了構造器,比如:

class A{
	A(int a){}
}
public class Test{
	public static void main(String[] args){
		A a = new A();
	}
}

這就是錯誤的,因為你已經有了構造器,就不會再為你建立那個無參構造器了。

方法過載

方法名相同,用引數型別不同進行區分,也可以用引數順序不同作為區分,注:這裡的順序不同指的是型別順序不同,如:function(String s,int i)和function(int i,String s)
基本型別的過載: 基本型別能從一個“較小”的型別自動提升到一個較大的型別,涉及到過載,可能會引起混亂。
但是對於char略有不同,在無法找到接收char引數的方法時,會直接提升到int型而不是經過byte, short再到int。
如果接受的較小的引數,而要傳的是較大的引數,那麼,就要通過型別轉換來執行窄化轉換
比如:

int x;
function(char(x));

在構造器中使用構造器

在為一個類寫了多個構造器,為了避免程式碼重複,可能會想在一個構造器裡呼叫另一個構造器,這樣使用是沒有問題的,但是隻能使用一個,不能使用多個構造器。如下:

public class A{
	int  x;
	String y;
	A(int x){this.x = x;}
	A(String y){this.y=y;}
	A(int x,String y){
		A(x);
		//A(y);//只能和A(x)存在一個,不能兩個一起用
		this.y=y;
	}
}

只能這麼使用,而不能呼叫兩個構造器.另外構造器必須在最起始處,否則會報錯。

垃圾回收

在類中允許呼叫一個名為finalize()的方法,它是在垃圾回收器準備好釋放物件佔用的空間時,將首先呼叫finalize方法。並且在下一次垃圾回收動作發生時,才會真正回收物件空間。
需要注意,finalize不等於C++裡面的解構函式。
對於垃圾回收要記住三點:

  1. 物件可能不被垃圾回收
  2. 垃圾回收並不等於析構
  3. 垃圾回收只與記憶體有關

finalize一般用在呼叫本地方法(非java程式碼)的時候。因為在本地的方法中,可能會有malloc這種申請記憶體空間的,不是物件,垃圾回收器無法回收,只能在finalize中寫方法釋放。

垃圾回收器機制

  1. 標記-清掃:
    遍歷所有引用,找出所有存活的物件,每當找到一個就給其進行標記,這個過程不會回收任何物件,標記全部完成,清理動作才開始,清理過程不會發生複製,剩下的堆空間也不是連續的。進入穩定狀態後用。
  2. 停止-複製:
    垃圾回收動作不會在後臺執行,垃圾回收發生的時候,程式會被暫停,然後將當前所有存活的物件從當前堆複製到另一堆,沒有被複制的全是垃圾,複製到新堆後保持緊湊排列。一般狀態用。

初始化

物件的建立過程假設有個名為Dog的類

  1. 當首次建立Dog型別時,或者Dog類的靜態方法/靜態域被訪問時,java直譯器必須查詢類路徑,以定位Dog.class檔案
  2. 然後載入Dog.class檔案,有關靜態初始化的所有動作都會被執行。因此,靜態初始化只在類被載入的時候執行一次。
  3. 當用new Dog()建立物件時,首先為其分配足夠的空間。
  4. 這塊儲存空間會被清零,這樣就自動的為物件中的所有基本型別資料都設定成了預設值,而引用則被設定成了null
  5. 執行所有出現於欄位定義處的初始化動作。
  6. 執行構造器。

靜態與非靜態例項初始化

首先看下面這段程式碼,就是非靜態例項的初始化:

class A{
	A(int i){
		System.out.println("a:"+i);
	}
}

class As{
	static A a1;
	static A a2;
	 {
		a1=new A(1);
		a2=new A(2);
	}
	As(){
		System.out.println("end");
	}
}
public class ChuShiHua {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		As as1= new As();
		As as2= new As();
	}

}

在看這段靜態例項的初始化:

class A{
	A(int i){
		System.out.println("a:"+i);
	}
}

class As{
	static A a1;
	static A a2;
	static{
		a1=new A(1);
		a2=new A(2);
	}
	As(){
		System.out.println("end");
	}
}
public class ChuShiHua {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		As as1= new As();
		As as2= new As();
	}

}

區別只有一個,就是個static關鍵字的事,但是輸出卻完全不一樣。
非靜態輸出為:

a:1
a:2
end
a:1
a:2
end

靜態輸出為:

a:1
a:2
end
end

其原因就是靜態只在類被載入的時候執行一次。

陣列初始化

陣列可以用new來初始化空間,即使是基本型別也可以。可以看如下程式碼:

public class ArrayNew {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] a;
		a=new int[10];
		System.out.println(a.length);
	}

}
輸出:
10