
new
,然後一切就緒了:)這裡我們將討論當我們寫的時候計算機和 Java 機器內部發生了什麼,例如:
Cat cat = new Cat();
我們之前已經討論過這個問題,但為了以防萬一,我們會提醒您:
- 首先,分配存儲對象的內存。
- 接下來,Java 機器創建對象的引用(在我們的例子中,引用是 Cat cat)。
- 最後,初始化變量並調用構造函數(我們將更詳細地研究這個過程)。

public class Vehicle {
public static int vehicleCounter = 0;
private String description = "Vehicle";
public Vehicle() {
}
public String getDescription() {
return description;
}
}
public class Truck extends Vehicle {
private static int truckCounter = 0;
private int yearOfManufacture;
private String model;
private int maxSpeed;
public Truck(int yearOfManufacture, String model, int maxSpeed) {
this.yearOfManufacture = yearOfManufacture;
this.model = model;
this.maxSpeed = maxSpeed;
Vehicle.vehicleCounter++;
truckCounter++;
}
}
該類Truck
是卡車的一個實現,其中包含代表其年份、型號和最大速度的字段。現在我們要創建一個這樣的對象:
public class Main {
public static void main(String[] args) throws IOException {
Truck truck = new Truck(2017, "Scania S 500 4x2", 220);
}
}
對於 Java 機器,該過程將如下所示:
-
發生的第一件事是類的靜態變量
Vehicle
被初始化。是的,我說的是Vehicle
類,不是Truck
。靜態變量在調用構造函數之前初始化,這從父類開始。讓我們嘗試驗證這一點。vehicleCounter
我們將類中的字段設置Vehicle
為 10 並嘗試在Vehicle
和Truck
構造函數中顯示它。public class Vehicle { public static int vehicleCounter = 10; private String description = "Vehicle"; public Vehicle() { System.out.println(vehicleCounter); } public String getDescription() { return description; } } public class Truck extends Vehicle { private static int truckCount = 0; private int yearOfManufacture; private String model; private int maxSpeed; public Truck(int yearOfManufacture, String model, int maxSpeed) { System.out.println(vehicleCounter); this.yearOfManufacture = yearOfManufacture; this.model = model; this.maxSpeed = maxSpeed; Vehicle.vehicleCounter++; truckCount++; } }
我們特意將 println 語句放在構造函數的最開頭,以確保在顯示
Truck
時卡車的字段尚未初始化。vehicleCounter
結果如下:
10 10
-
父類的靜態變量初始化完成後,再對子類的靜態變量進行初始化。在我們的例子中,這是班級
truckCounter
的領域Truck
。讓我們做另一個實驗,我們將嘗試在初始化其他字段之前顯示構造函數
truckCounter
內部的值:Truck
public class Truck extends Vehicle { private static int truckCounter = 10; private int yearOfManufacture; private String model; private int maxSpeed; public Truck(int yearOfManufacture, String model, int maxSpeed) { System.out.println(truckCounter); this.yearOfManufacture = yearOfManufacture; this.model = model; this.maxSpeed = maxSpeed; Vehicle.vehicleCounter++; truckCounter++; } }
如您所見,在構造函數開始時,值 10已經分配給我們的靜態變量
Truck
。 -
現在還不是構造函數的時間!變量初始化繼續。 第三次初始化父類的非靜態變量。 如您所見,繼承使創建對象的過程變得非常複雜,但是您對此無能為力:您只需要記住編程中的一些東西:)
作為實驗,我們可以
description
在Vehicle
類中為變量賦一些初始值,然後在構造函數中更改它。public class Vehicle { public static int vehicleCounter = 10; private String description = "Initial value of the description field"; public Vehicle() { System.out.println(description); description = "Vehicle"; System.out.println(description); } public String getDescription() { return description; } }
讓我們運行
main()
創建卡車的方法:public class Main { public static void main(String[] args) throws IOException { Truck truck = new Truck(2017, "Scania S 500 4x2", 220); } }
我們得到以下結果:
Initial value of the description field Vehicle
這證明在
Vehicle
構造函數開始時,該description
字段已經被賦值。 -
最後,是構造函數的時間了! 更準確地說,是基類構造函數的時候了。它在對象創建過程的第四步被調用。
這也很容易驗證。讓我們嘗試向控制台輸出兩行:一行在
Vehicle
基類構造函數中,第二行在Truck
構造函數中。我們需要確信Vehicle
首先顯示裡面的行:public Vehicle() { System.out.println("Hello from the Vehicle constructor!"); } public Truck(int yearOfManufacture, String model, int maxSpeed) { System.out.println("Hello from the Truck constructor!"); this.yearOfManufacture = yearOfManufacture; this.model = model; this.maxSpeed = maxSpeed; Vehicle.vehicleCounter++; truckCounter++; }
我們將運行我們的
main()
方法並查看結果:Hello from the Vehicle constructor! Hello from the Truck constructor!
出色的。這意味著我們沒有弄錯 :) 讓我們繼續。
-
現在是初始化子類(即我們的類)的非靜態字段的
Truck
時候了。被實例化的類中的字段直到第五步才被初始化!令人驚訝,但確實如此 :) 同樣,我們將做一個簡單的檢查——就像父類一樣:我們將一些初始值賦給變量,maxSpeed
並在Truck
構造函數中檢查該值是否在構造函數啟動之前分配:public class Truck extends Vehicle { private static int truckCounter = 10; private int yearOfManufacture; private String model; private int maxSpeed = 150; public Truck(int yearOfManufacture, String model, int maxSpeed) { System.out.println("Initial value of maxSpeed = " + this.maxSpeed); this.yearOfManufacture = yearOfManufacture; this.model = model; this.maxSpeed = maxSpeed; Vehicle.vehicleCounter++; truckCounter++; } }
控制台輸出:
Initial value of maxSpeed = 150
可以看到, 構造函數啟動時
Truck
,maxSpeed
已經等於150了! -
Truck
調用子類的構造函數。只有在這一點上,最後,我們正在實例化的類的構造函數才會被調用!
只有在第六步中,這些字段才會被賦予我們作為參數傳遞給卡車的值。
如您所見,“構建”一輛卡車,即對象創建過程,並不簡單。但我們似乎已將其分解為最小的部分 :)

GO TO FULL VERSION