定義類
| 導航類和物件主題: |
Java 中的每個類都可以由以下元素組成
- 欄位、成員變數或例項變數 — 欄位是儲存特定於每個物件的資料的變數。例如,員工可能有一個 ID 號碼。每個類物件都有一個欄位。
- 成員方法或例項方法 — 成員方法對物件執行操作。例如,員工可能有一個方法來簽發他的工資單或訪問他的姓名。
- 靜態欄位或類欄位 — 靜態欄位對於相同類的任何物件都是通用的。例如,Employee 類中的靜態欄位可以跟蹤發行的最後一個 ID 號碼。每個靜態欄位在類中只存在一次,無論為該類建立了多少物件。
- 靜態方法或類方法 — 靜態方法是不影響特定物件的方法。
- 內部類 — 有時在另一個類中包含一個類很有用,如果它在類外部沒有用或不應該在類外部訪問。
- 建構函式 — 生成新物件的特殊方法。
- 引數化型別 — 從 1.5 開始,引數化型別可以在定義期間分配給類。引數化型別將在類例項化時被指定型別替換。這是由編譯器完成的。它類似於 C 語言宏“#define”語句,其中預處理器評估宏。
程式碼清單 4.1:Employee.java
public class Employee { // This defines the Employee class.
// The public modifier indicates that
// it can be accessed by any other class
private static int nextID; // Define a static field. Only one copy of this will exist,
// no matter how many Employees are created.
private int myID; // Define fields that will be stored
private String myName; // for each Employee. The private modifier indicates that
// only code inside the Employee class can access it.
public Employee(String name) { // This is a constructor. You can pass a name to the constructor
// and it will give you a newly created Employee object.
myName = name;
myID = nextID; // Automatically assign an ID to the object
nextID++; // Increment the ID counter
}
public String getName() { // This is a member method that returns the
// Employee object's name.
return myName; // Note how it can access the private field myName.
}
public int getID() { // This is another member method.
return myID;
}
public static int getNextID() { // This is a static method that returns the next ID
// that will be assigned if another Employee is created.
return nextID;
}
}
|
以下 Java 程式碼將生成此輸出
|
|
建構函式在物件分配後立即被呼叫來初始化物件
程式碼清單 4.3:Cheese.java
public class Cheese {
// This is a constructor
public Cheese() {
System.out.println("Construct an instance");
}
}
|
通常,建構函式使用new關鍵字呼叫
程式碼部分 4.1:建構函式呼叫。
Cheese cheese = new Cheese();
|
建構函式語法與方法語法類似。但是,建構函式的名稱與類的名稱相同(大小寫相同),並且建構函式沒有返回型別。第二點是最重要的區別,因為方法也可以與類具有相同的名稱,這是不推薦的
程式碼清單 4.4:Cheese.java
public class Cheese {
// This is a method with the same name as the class
public void Cheese() {
System.out.println("A method execution.");
}
}
|
返回的物件始終是一個有效的、有意義的物件,而不是依賴於單獨的初始化方法。建構函式不能是abstract、final、native、static、strictfp或synchronized。但是,建構函式像方法一樣可以過載並接受引數。
程式碼清單 4.5:Cheese.java
public class Cheese {
// This is a constructor
public Cheese() {
doStuff();
}
// This is another constructor
public Cheese(int weight) {
doStuff();
}
// This is yet another constructor
public Cheese(String type, int weight) {
doStuff();
}
}
|
按照慣例,接受其自身型別物件的建構函式並複製資料成員稱為複製建構函式。建構函式的一個有趣的特性是,如果你沒有在你的類中指定建構函式,那麼編譯器會為你建立一個。如果寫出來,這個預設建構函式看起來像
程式碼清單 4.6:Cheese.java
public class Cheese {
public Cheese() {
super();
}
}
|
super()命令呼叫超類的建構函式。如果沒有明確呼叫super(...)或this(...),那麼預設超類建構函式super();將在建構函式主體執行之前被呼叫。也就是說,在某些情況下,您需要手動新增呼叫。例如,如果您編寫了一個建構函式,無論它接受什麼引數,編譯器都不會新增預設建構函式。程式碼清單 4.8會導致執行時錯誤
程式碼清單 4.7:Cheese.java
public class Cheese {
public Cheese(int weight, String type) {
doStuff();
}
}
|
程式碼清單 4.8:Mouse.java
public class Mouse {
public void eatCheese() {
Cheese c = new Cheese(); // Oops, compile time error!
}
}
|
在擴充套件現有類時,請牢記這一點。要麼建立一個預設建構函式,要麼確保每個繼承你的類的類都使用正確的建構函式。
初始化器是與欄位初始化器同時執行的程式碼塊。
靜態初始化器是與靜態欄位初始化器同時執行的程式碼塊。靜態欄位初始化器和靜態初始化器按宣告順序執行。靜態初始化在類載入後執行。
程式碼部分 4.2:靜態初始化器。
static int count = 20;
static int[] squares;
static { // a static initializer
squares = new int[count];
for (int i = 0; i < count; i++)
squares[i] = i * i;
}
static int x = squares[5]; // x is assigned the value 25
|
例項初始化器是程式碼塊,它們在例項(非static)欄位的初始化器執行的同時執行。例項欄位初始化器和例項初始化器按宣告順序執行。例項初始化器和例項欄位初始化器都在建構函式呼叫期間執行。初始化器在呼叫超類建構函式後立即執行,並在建構函式主體之前執行。