Java 變數範圍 (Scope)
變數範圍決定變數在哪裡可以被存取。
區域變數 (Local Variables)
在方法、建構子或區塊內宣告的變數:
public void method() {
int x = 10; // 區域變數
System.out.println(x); // 可以存取
} // x 在這裡結束
// System.out.println(x); // 錯誤!x 不存在
區塊範圍
public void test() {
int a = 1;
if (true) {
int b = 2; // 區塊內的區域變數
System.out.println(a); // 可以存取外層的 a
System.out.println(b); // 可以
}
System.out.println(a); // 可以
// System.out.println(b); // 錯誤!b 不存在
}
迴圈變數
for (int i = 0; i < 5; i++) {
System.out.println(i); // 可以
}
// System.out.println(i); // 錯誤!i 不存在
實例變數 (Instance Variables)
在類別內、方法外宣告的變數,屬於物件:
public class Person {
private String name; // 實例變數
private int age; // 實例變數
public void setName(String name) {
this.name = name; // 使用 this 區分
}
public void printInfo() {
System.out.println(name + ", " + age);
}
}
每個物件有自己的實例變數:
Person p1 = new Person();
Person p2 = new Person();
p1.setName("Alice");
p2.setName("Bob");
// p1 和 p2 有各自的 name
類別變數 (Class Variables)
使用 static 宣告的變數,屬於類別,所有物件共享:
public class Counter {
private static int count = 0; // 類別變數
public Counter() {
count++;
}
public static int getCount() {
return count;
}
}
Counter c1 = new Counter(); // count = 1
Counter c2 = new Counter(); // count = 2
Counter c3 = new Counter(); // count = 3
System.out.println(Counter.getCount()); // 3
變數遮蔽
區域變數可以和實例變數同名,會遮蔽實例變數:
public class Example {
private int value = 10; // 實例變數
public void method() {
int value = 20; // 區域變數,遮蔽實例變數
System.out.println(value); // 20(區域變數)
System.out.println(this.value); // 10(實例變數)
}
}
參數遮蔽
public class Person {
private String name;
public void setName(String name) {
// 參數 name 遮蔽了實例變數 name
this.name = name; // 使用 this 指向實例變數
}
}
變數生命週期
| 變數類型 | 建立時機 | 銷毀時機 |
|---|---|---|
| 區域變數 | 進入區塊 | 離開區塊 |
| 實例變數 | 物件建立 | 物件被 GC |
| 類別變數 | 類別載入 | 類別卸載 |
存取修飾詞
控制變數的可見範圍:
public class Example {
public int publicVar; // 任何地方都可存取
protected int protectedVar;// 同套件和子類別可存取
int defaultVar; // 同套件可存取
private int privateVar; // 只有本類別可存取
}
常見錯誤
使用未初始化的區域變數
public void method() {
int x;
// System.out.println(x); // 編譯錯誤!
x = 10;
System.out.println(x); // OK
}
在錯誤的範圍存取變數
public void method() {
if (true) {
int x = 10;
}
// System.out.println(x); // 錯誤!x 不在範圍內
}
混淆區域變數和實例變數
public class Example {
private int value = 100;
public void confusing(int value) {
// 這裡的 value 是參數,不是實例變數
System.out.println(value); // 參數值
System.out.println(this.value); // 100
}
}
最佳實踐
- 最小範圍原則:變數範圍越小越好
- 避免變數遮蔽:除非有明確理由
- 及時初始化:宣告時就初始化
- 有意義的命名:避免混淆
// 好的做法
for (int i = 0; i < arr.length; i++) {
int current = arr[i]; // 最小範圍
// 使用 current
}
// 不好的做法
int i; // 範圍太大
int current;
for (i = 0; i < arr.length; i++) {
current = arr[i];
// ...
}