public void method() {
String s; // 編譯錯誤:可能未初始化
System.out.println(s);
}
// 修正:必須顯式初始化
public void method() {
String s = null; // 或具體值
System.out.println(s); // 輸出 null
}
對比:成員變數(實例/靜態)有默認值(null/0/false),局部變數無。
public void method() {
public int x = 1; // 編譯錯誤:局部變數不能有 public/protected/private
final int y = 2; // ✅ 僅可用 final
}
public void method(final int x) {
x = 10; // 編譯錯誤:final 參數不可重新賦值
}
public void method(final StringBuilder sb) {
sb.append("hello"); // ✅ 允許:修改對象內部狀態
sb = new StringBuilder(); // ❌ 編譯錯誤:改變引用指向
}
public class Demo {
final int x; // 編譯錯誤:final 實例變數無默認值,必須初始化
// 正確初始化位置(三選一):
// 1. 聲明時
final int a = 1;
// 2. 實例初始化塊
{ final int b; b = 2; }
// 3. 構造器中(所有構造器都必須初始化)
public Demo() { x = 3; }
public Demo(int val) { x = val; }
}
Java 只有值傳遞。基本型別傳值的副本,引用型別傳引用的副本(地址值)。
public class ParameterPassing {
// 基本型別:無法修改原值
public void changePrimitive(int value) {
value = 10;
}
// 引用型別:無法修改原引用,但可修改對象內容
public void changeReference(Wrapper wrapper) {
wrapper.value = 20; // ✅ 修改對象內容:影響原對象
wrapper = new Wrapper(); // ❌ 修改引用副本:不影響原引用
wrapper.value = 30;
}
// 交換失敗示範
public void swap(Wrapper a, Wrapper b) {
Wrapper temp = a;
a = b;
b = temp; // 僅交換了局部引用副本
}
static class Wrapper { int value; }
public static void main(String[] args) {
ParameterPassing demo = new ParameterPassing();
int primitive = 5;
demo.changePrimitive(primitive);
System.out.println("primitive: " + primitive); // 5,未變
Wrapper ref = new Wrapper();
ref.value = 10;
demo.changeReference(ref);
System.out.println("ref.value: " + ref.value); // 20,內容被修改!
Wrapper a = new Wrapper(); a.value = 1;
Wrapper b = new Wrapper(); b.value = 2;
demo.swap(a, b);
System.out.println("a=" + a.value + ", b=" + b.value); // a=1, b=2,未交換
}
}
調用棧幀:
main():
primitive = 5 (int)
ref = 0x7f00 (引用地址) ──────┐
▼
堆:
Wrapper@0x7f00 { value: 10 } ◄─┘
changeReference(Wrapper wrapper):
wrapper = 0x7f00 (引用副本) ────┐
▼
堆 (同一對象):
Wrapper@0x7f00 { value: 20 } ◄──┘ ← 內容修改可見
wrapper = new Wrapper() (0x8a00) ← 僅改變局部副本指向,main 的 ref 不變
| 場景 | 錯誤預期 | 實際行為 | 正確做法 |
|---|---|---|---|
| 方法修改參數對象屬性 | 不影響原對象 | 影響原對象 | 明確文檔:此方法會修改傳入對象狀態 |
| 方法重新賦值參數 | 影響原引用 | 不影響 | 返回新對象,調用者接收返回值 |
| 交換兩個對象引用 | 交換成功 | 失敗 | 返回包含兩值的對象/數組,或用 AtomicReference |
| 集合添加元素 | 不影響原集合 | 影響原集合 | 傳入不可變視圖 Collections.unmodifiableList() |