public class T1 {
class Child {
int no;
Child nextChild = null;
public Child(int no) { this.no = no; }
}
class CycLink {
Child temp = null;
Child firstChild = null;
public void create() {
for (int i = 1; i <= 5; i++) {
if (i == 1) {
Child ch = new Child(i);
this.temp = ch;
this.firstChild = ch;
} else {
Child ch = new Child(i);
temp.nextChild = ch; // 關鍵行
temp = ch;
}
}
}
}
}
temp.nextChild 是什麼意思?temp 是 Child 類型的引用變量,指向某個 Child 對象nextChild 是 Child 類中的實例字段,類型也是 Child(即引用類型)temp.nextChild 表示:通過 temp 引用訪問其指向對象的 nextChild 字段temp 存儲對象地址,. 操作符根據地址找到對象,訪問其成員不能直接用對象調用,Java 中只能通過引用操作對象:
// 錯誤認知:對象.字段
Child obj = new Child(1);
obj.nextChild = ...; // 這裡的 obj 其實是引用變量!
// 正確理解:
Child ref = new Child(1); // ref 是引用,new Child(1) 創建對象
ref.nextChild = ...; // 通過引用訪問對象字段
棧內存 (Stack) 堆內存 (Heap)
┌─────────────────┐ ┌────────────────────────┐
│ main 方法棧幀 │ │ │
├─────────────────┤ │ Child 對象 @0x7f... │
│ Child ref = 0x7f... ──────────►│ no = 1 │
│ │ │ nextChild = null │
└─────────────────┘ └────────────────────────┘
引用變量 ref 實際對象
(4/8 字節) (對象頭 + 實例數據)
| 特性 | 對象 | 引用 |
|---|---|---|
| 存儲位置 | 堆內存 | 棧內存(局部變量)/ 堆內存(字段) |
| 大小 | 動態,含對象頭、實例字段、對齊填充 | 固定 4 字節(32位)或 8 字節(64位壓縮指針) |
| 生命周期 | 從 new 到 GC 回收 | 作用域結束或置 null 時失效 |
| 可直接操作 | 否 | 是(. 訪問字段/調用方法) |
| 賦值語義 | 無直接賦值 | 複製地址(淺拷貝) |
| == 比較 | 編譯錯誤 | 比較地址(是否指向同一對象) |
// 迭代 1: i=1
Child ch = new Child(1); // 創建對象 @0x100
temp = ch; // temp → @0x100
firstChild = ch; // firstChild → @0x100
// 迭代 2: i=2
Child ch = new Child(2); // 創建對象 @0x200
temp.nextChild = ch; // @0x100.nextChild = @0x200 (關鍵!)
temp = ch; // temp → @0x200
// 迭代 3: i=3
Child ch = new Child(3); // 創建對象 @0x300
temp.nextChild = ch; // @0x200.nextChild = @0x300
temp = ch; // temp → @0x300
// ... 以此類推
// 最終鏈表結構:
// firstChild → @0x100 (no=1) → @0x200 (no=2) → @0x300 (no=3) → @0x400 (no=4) → @0x500 (no=5) → null
// ↑ ↑
// firstChild temp (最後指向尾節點)
null.nextChild 拋 NullPointerException。null,基本類型有各自默認值(0、false 等)。