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++裡面的解構函式。
對於垃圾回收要記住三點:
- 物件可能不被垃圾回收
- 垃圾回收並不等於析構
- 垃圾回收只與記憶體有關
finalize一般用在呼叫本地方法(非java程式碼)的時候。因為在本地的方法中,可能會有malloc這種申請記憶體空間的,不是物件,垃圾回收器無法回收,只能在finalize中寫方法釋放。
垃圾回收器機制
- 標記-清掃:
遍歷所有引用,找出所有存活的物件,每當找到一個就給其進行標記,這個過程不會回收任何物件,標記全部完成,清理動作才開始,清理過程不會發生複製,剩下的堆空間也不是連續的。進入穩定狀態後用。 - 停止-複製:
垃圾回收動作不會在後臺執行,垃圾回收發生的時候,程式會被暫停,然後將當前所有存活的物件從當前堆複製到另一堆,沒有被複制的全是垃圾,複製到新堆後保持緊湊排列。一般狀態用。
初始化
物件的建立過程假設有個名為Dog的類
- 當首次建立Dog型別時,或者Dog類的靜態方法/靜態域被訪問時,java直譯器必須查詢類路徑,以定位Dog.class檔案
- 然後載入Dog.class檔案,有關靜態初始化的所有動作都會被執行。因此,靜態初始化只在類被載入的時候執行一次。
- 當用new Dog()建立物件時,首先為其分配足夠的空間。
- 這塊儲存空間會被清零,這樣就自動的為物件中的所有基本型別資料都設定成了預設值,而引用則被設定成了null
- 執行所有出現於欄位定義處的初始化動作。
- 執行構造器。
靜態與非靜態例項初始化
首先看下面這段程式碼,就是非靜態例項的初始化:
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