不少類都包含一個無參數的構造函數,對象由無參數構造函數建立時,其狀態會設置爲適當的默認值。例如,以下是Employee的無參數構造函數:java
pubilc Employee() { name = ""; salary = 0; hireDay = new Date(); }
因爲類的構造器方法能夠重載,因此能夠採用多種形式設置類的實例域的初始狀態。確保無論怎麼調用構造器,每一個實例域均可以被設置爲一個有意義的數初值。這是一種很好的設計習慣。
能夠在類的定義中,直接將一個值付給任何域。例如:數組
class A{} Class Employee { private String name = ""; private A a = new A(); }
在執行構造器以前先執行賦值操做。當一個類的全部構造器都但願把相同的值賦給某個特定的實例域時,這種方式特別有用。
初始值不必定是常量。在下面這個例子中,能夠調用方法對域進行初始化。Employee類中每一個僱員都有一個id域。可使用下列方式進行初始化:app
class Employee{ private static int nextId; private int id = assignId(); private static int assignId() { int r = nextId(); nextId++; return r; } }
這個方法也可帶有參數,但這些參數必須是已經初始化的了。所以,能夠這樣寫:ide
public class MethodInit { int i = f(); int j = g(i); int f() {return 11;} int g(int n ) {return n* 10;}
但像下面這樣就不對了:函數
public class MethodInit{ int j = g(i); //Illegal forward reference int i = f(); int f() {return 11;} int g(int n) {return n * 1
前面已經講過兩種初始化數據域的方法:this
class Employee{ private static int nextId; private int id; private String name; private double salary; //object initialization block { id = nextId; nextId++; } public Employee(String n, dobule s) { name = n; salary = s; } public Employee(){ name = ""; salary = 0; } }
在這個示例中,不管使用哪一個構造器構造對象,id域都在對象初始化塊中被初始化。首先運行初始化塊,而後才運行構造器的主體部分。設計
假設你但願在方法的內部得到對當前對象的引用,就可使用this關鍵字。this關鍵字只能在方法的內部使用,表示對「調用這個方法的那個對象」的引用。this的用法和其餘對應引用並沒有不一樣。只要注意,若是在方法內部調用同一個類的另外一個方法,就沒必要使用this,直接調用便可。code
只有當須要明確指出對當前對象的引用時,才須要使用this關鍵字。例如,當須要返回對當前對象的引用時,就經常須要在return語句裏這樣寫:對象
public class Leaf{ int i = 0; Leaf increment() { i++: return this; } } public static void main(String[] args) { Leaf x = new Leaf(); x.increment().increment().increment(); }
因爲increment()經過this關鍵字返回了對當前對象的引用,因此很容易在一條語句中對同一個對象進行屢次操做。
this關鍵字對於將對於將當前對象傳遞給其餘對象也頗有用:ci
Class Person{ public void eat(Apple apple) { Apple peeled = apple.getPeeled(); System.out.println("Yummy"); } } class Peeler { static Apple peel(Apple apple) { //... remove peel return apple; //Peeled } } class Apple{ Apple getPeeled() {return Peeler.peel(this);} } public class PassingThis { public static void main(Strings[] args) { new Person.eat(new Apple)); } }
構造器的的參數名和引用以下所示:
Class Employee{ private String name; private double salary; public Employee(String name , double salary) { this.name = name; this.salary = salary; } }
它基於這樣一個事實:參數變量用一樣的名字將實例域屏蔽起來。例如,若是將參數命名爲salary,salary將引用這個參數,而不是實例域。可是,能夠採用this的形式訪問實例域。
若是構造器的第一個句子形如(this...),這個構造器將調用同一個類的另外一個構造器。下面是一個典型的例子:
public Employee() { //calls Employee(String, double) this("Employee #" + nextId, s); nextId++; }
儘管能夠用this調用另外一個構造器,但卻不能同時調用兩個。此外,必須將構造器調用置於方法最起始處,不然編譯器會報警。
***
Class A{ private static B b = new B(); }
3.也能夠用使用指定初始化,不過要在初始化塊的外面加 static關鍵字
class Cup{ Cup(int marker) { } } class Cups{ static Cup cup1; static Cup cup2; static { cup1 = new Cup(1); cup2 = new Cup(2); } Cup() { print("Cups()"); } } public class ExplicitStatic { public static void main(Strings[] args) { print("Inside main()"); Cups.cup1.f(99); } static Cups cups1 = new Cups(); static Cups cups2 = new Cups(); }
不管是經過標爲(1)的那行代碼訪問靜態的cup1對象,仍是把標爲(1)的行註釋掉,讓它去運行標爲(2)的那行代碼(即解除標爲(2)的行的註釋),Cups的靜態初始化動做都會獲得執行。若是把標爲(1)和(2)的行同時註釋掉,Cups的靜態初始化動做就不會進行。此外,激活一行仍是兩行標爲(2)的代碼(即解除註釋)都可有可無,靜態初始化動做只進行一次。
數組初始化主要有兩種形式。第一種以下:
//Aggregate initialization BerylliumSphere[] d = { new BerylliumSphere(), new BerylliumSphere(), new BerylliumSphere()};
數組d代表使用"彙集初始化"語法建立數組對象,而且以BerylliumSphere對象將其初始化的過程,可是這個操做必須在定義d的位置使用。
第二種以下:
//Dynamic aggregate initialization a = new BerylliumSphere[] { new BerylliumSphere(), new BerylliumSphere() };
這種方法被看做是"動態的彙集初始化",這種方法能夠在任意位置建立和初始化數組對象。例如,假設方法hide()須要一個BerylliumSpere對象的數組做爲輸入參數。能夠以下調用:
hide(d);
但也能夠動態地建立將要做爲參數傳遞的數組:
hide(new BerylliumSpere[]{new BerylliumSpere()}
雙括號初始化利用了內部類的語法。假設想構造一個數組列表,並將它傳遞到一個方法。
ArrayList<String> friends = new ArrayList<>(); friends.add("Harrys"); friends.add("Tony"); invite(friends);
若是不須要這個數組列表,最好讓它做爲一個匿名列表。不過做爲一個匿名列表,添加元素方法以下:
invite(new ArrayList<String>(){{add("Harrys");add(""Tony"")}})
注意這裏的雙括號。外括號創建了Arraylist的一個匿名子類。內括號則是一個對象構造塊。