Chapter 5 初始化與清理

this 關鍵字

 

1)this 關鍵字只能在方法內部使用,表示對“調用方法的那個對象”的引用。

 

2)可以用this 調用一個構造器,但不能用相同的方法調用兩個構造器。例如:

    Flower(int petals) {
        petalCount = petals;
        print("Constructor w/ int arg only, petalCount= "
                + petalCount);
    }

    Flower(String ss) {
        print("Constructor w/ String arg only, s = " + ss);
        s = ss;
    }

    Flower(String s, int petals) {
        this(petals);
        // ! this(s); // Can't call two!
        this.s = s; // Another use of "this"
        print("String & int args");
    }


除構造器之外,編譯器禁止在其他任何方法中調用構造器。例如:

    void printPetalCount() {
        // ! this(11); // Not inside non-constructor!
        print("petalCount = " + petalCount + " s = " + s);
    }

 


構造器初始化 

 

1)在類的內部,變量定義的先後順序決定了初始化的順序。

 

2)static關鍵字不能應用於局部變量,它只能作用於域。

 

3)初始化的順序是先“靜態”,(如果它們尚未因前面的對象創建過程而被初始化),後“非靜態”。

 

4)對象的創建過程會很有幫助。假設有個名爲 Dog 的類:


1. 當首次創建類型爲 Dog 的對象時(構造器可以看成靜態方法),或者Dog 類的靜態方法/靜態域首次被訪問時,Java 解釋器必須查找類路徑,以定位Dog.class 文件。


2. 然後載入 Dog.class(這將創建一個Class 對象),有關靜態初始化的動作都會執行。因此,靜態初始化只在Class 對象首次加載的時候進行一次。


3. 當用 new Dog( )創建對象的時候,首先將在堆上爲Dog 對象分配足夠的存儲空間。


4. 這塊存儲空間會被清零,這就自動地將Dog 中的所有基本類型數據設置成了默認值(對數字來說就是0,對布爾型和字符型也相同),而引用則被設置成了null。


5. 執行所有出現於域定義處的初始化動作。


6. 執行構造器。這可能會牽涉到很多動作,尤其是涉及繼承的時候。

 

數組初始化

 

1)編譯器不允許你指定數組的大小。

 

2)數組的三種初始化方法,以及注意事項。

	/**
	 * 數組的三種初始化方式,數組在定義時不可以指定數組的大小
	 * */
	class ArrayTest {
		/**
		 * 第一種,在定義時進行初始化。 這種形式的初始化只可以在定義處使用。
		 * */
		Integer[] integer0 = { 1, 2, 3 };
		/**
		 * 第二種,在new對象時初始化。 這種形式的初始化不可以指定數組的大小
		 * */
		Integer[] integer1 = new Integer[] { 1, 2, 3 };
		/**
		 * 第三種,利用循環逐一初始化。 這種形式的初始化必須指定數組的大小。 在這種方式下,如果數組存儲的數據類型是基本數據類型,
		 * 在數組通過new完成初始化後,所有的數組元素被初始化爲該類型的默認值; 如果數組存儲的是對象,則所有的數組元素被初始化爲null。
		 * */
		Integer[] integer2 = new Integer[3];
		{

			for (int i = 0; i < integer2.length; i++) {
				integer2[i] = i;
			}
		}

	}


3)數組和可變參數列表

對於參數個數和參數類型 未知的場合,可以使用數組的第二種初始化方法來產生一個可變參數列表,例如:

class A {
}

public class VarArgs {
	static void printArray(Object[] args) {
		for (Object obj : args)
			System.out.print(obj + " ");
		System.out.println();
	}

	public static void main(String[] args) {
		printArray(new Object[] { new Integer(47), new Float(3.14),
				new Double(11.11) });
		printArray(new Object[] { "one", "two", "three" });
		printArray(new Object[] { new A(), new A(), new A() });
	}
} 


而在java5中,可以像下面這樣定義可變參數列表:

class A {
}

public class NewVarArgs {
	static void printArray(Object... args) {
		for (Object obj : args)
			System.out.print(obj + " ");
		System.out.println();
	}

	public static void main(String[] args) {
		// Can take individual elements:
		printArray(new Integer(47), new Float(3.14), new Double(11.11));
		printArray(47, 3.14F, 11.11);
		printArray("one", "two", "three");
		printArray(new A(), new A(), new A());
		// Or an array:
		printArray(new Integer[] { 1, 2, 3, 4 });
		printArray(); // Empty list is OK
	}
}

有了可變參數列表,你就不用顯示地編寫 數組語法了,當你指定參數時,編譯器會爲你填充數組,你獲取的仍舊是一個數組。注意程序的倒數第二行,可變參數列表也可以接受一個數組作爲參數。

 

可變參數列表使得重載過程變得複雜:

public class OverloadingVarargs {
    static void f(Character... args) {
        System.out.print("first");
        for (Character c : args)
            System.out.print(" " + c);
        System.out.println();
    }

    static void f(Integer... args) {
        System.out.print("second");
        for (Integer i : args)
            System.out.print(" " + i);
        System.out.println();
    }

    static void f(Long... args) {
        System.out.println("third");
    }

    public static void main(String[] args) {
        f('a', 'b', 'c');
        f(1);
        f(2, 1);
        f(0);
        f(0L);
        // ! f(); // Won't compile -- ambiguous
    }
} 


在不使用參數調用f()時,編譯器無法知道應該調用哪個方法。你可能會通過在某個方法中添加一個非可變參數來解決該問題:

public class OverloadingVarargs2 {
    static void f(float i, Character... args) {
        System.out.println("first");
    }

    static void f(Character... args) {
        System.out.print("second");
    }

    public static void main(String[] args) {
        f(1, 'a');
//         f('a', 'b'); //Won't compile -- ambiguous  
    }
}


如果你給這兩個方法都添加一個非可變參數,就可以解決問題了:

public class OverloadingVarargs3 {
    static void f(float i, Character... args) {
        System.out.println("first");
    }

    static void f(char c, Character... args) {
        System.out.println("second");
    }

    public static void main(String[] args) {
        f(1, 'a');
        f('a', 'b');
    }
}


你應該總是隻在重載方法的一個版本上使用可變參數列表,或者壓根就不使用它。


 


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