代碼現場
public class Demo {
public A getA() { return new A(); }
public void test() {
B b = this.getA().getB(); // 方法鏈調用
}
}
class A {
public B getB() { return new B(); }
}
class B { }
執行流程圖解
this.getA().getB()
│
├─ 1. this → 當前 Demo 實例引用 (棧上)
│
├─ 2. .getA() → 調用 Demo.getA()
│ ├─ 創建新 A 實例 (堆上)
│ └─ 返回 A 引用 (壓入棧)
│
└─ 3. .getB() → 在步驟 2 返回的 A 引用上調用 getB()
├─ 創建新 B 實例 (堆上)
└─ 返回 B 引用 → 賦值給變量 b
等價展開形式(字節碼層面本質)
// 編譯器生成的等效代碼
A tempA = this.getA(); // 存儲中間引用到局部變量表
B tempB = tempA.getB(); // 基於中間引用調用
B b = tempB; // 最終賦值
核心特性
| 特性 | 說明 |
| 左結合性 | `a.b().c()` 等價於 `(a.b()).c()` |
| 中間結果臨時存儲 | 編譯器在局部變量表分配槽位保存中間引用,防止 GC 提前回收 |
| 空指鏈風險 | 任一環返回 `null` 即拋 NPE,需防御性編程或 Optional 鏈 |
| Builder 模式典型應用 | `new StringBuilder().append("a").append("b").toString()` |
最佳實踐:Optional 鏈式調用 (Java 8+)
// 避免 NPE 的優雅寫法
Optional.ofNullable(demo)
.map(Demo::getA)
.map(A::getB)
.ifPresent(b -> System.out.println("Got B: " + b));
// 或工具方法
public static <T, R> R safeGet(T obj, Function<T, R>... fns) {
return Arrays.stream(fns).reduce(Function.identity(), Function::andThen).apply(obj);
}
// 用法:B b = safeGet(demo, Demo::getA, A::getB);
總結
this.getA().getB() 是**語法糖**,本質是編譯器自動生成中間臨時變量的順序調用。理解其「左結合、中間引用入棧、空指鏈風險」三大特性,配合 Optional 或工具方法實現安全鏈式編程。