3秒でわかる
宣言した変数がどこから見えるかの範囲。Java では波かっこの内側が基本単位で、範囲を狭く保つことが名前の衝突や意図しない書き換えを防ぐ土台になる。
もう少し詳しく
どういうものか
宣言した変数や名前が、コードのどこから参照できるかという有効範囲のことです。Java では波かっこで囲まれたブロックが基本の単位で、ブロックの中で宣言した変数はその閉じかっこまでで消えます。
範囲は大きく分けて 3 段階あります。メソッドやブロックの中だけで生きるローカル変数、インスタンスごとに持つフィールド、クラス全体で 1 つだけ存在する static フィールドです。内側からは外側の名前が見えますが、外側から内側の名前は見えません。
なぜ必要か
見える範囲が広いほど、どこで書き換わったか分からなくなるからです。あらゆるメソッドから触れる変数を追いかけるには、クラス全体を読む必要があります。for 文の中だけで使う変数なら、その for 文だけ読めば済みます。読む量を減らす仕組みだと考えると分かりやすいです。
寿命の管理にも関わります。ローカル変数はブロックを抜ければ役目を終えますが、static フィールドはプログラムが動いている間ずっと残り続けます。不要になったデータを static に持たせ続けると、メモリを掴んだまま解放されない原因になります。
具体例
public class Cart {
private static int instanceCount = 0; // クラスに 1 つ
private int total = 0; // インスタンスごとに 1 つ
public Cart() {
instanceCount++;
}
public void addItems(int[] prices) {
int subtotal = 0; // このメソッドの中だけ
for (int i = 0; i < prices.length; i++) {
int price = prices[i]; // この for の中だけ
subtotal += price;
}
// System.out.println(price); // ここでは price は見えない
total += subtotal;
}
public int getTotal() {
// System.out.println(subtotal); // 他メソッドのローカル変数も見えない
return total;
}
}同じ名前を内側で宣言すると外側が隠れます。コンストラクタの引数とフィールドが同名になる場面が典型で、this を付けてどちらかを明示します。
public class User {
private String name;
public User(String name) {
this.name = name; // this を外すと引数に自分自身を代入するだけで終わる
}
}つまずきやすいところ
this を書き忘れ、フィールドが null のまま残る。コンパイルは通るので実行するまで気付けません似た用語との違い
| 用語 | 意味するもの |
|---|---|
| スコープ | 名前がどこから見えるかという範囲 |
| ライフタイム | その値がいつからいつまでメモリ上に存在するか |
| アクセス修飾子 | private や public など、クラスの外から触れるかどうかの制御 |
スコープは「見えるか」、ライフタイムは「残っているか」の話で、両者は必ずしも一致しません。