ローカルクラスを対策する
ローカルクラスとは、クラス内に定義されたメソッド内で定義されたクラスのことを指す。主なルールとしては下記の通りになっている。
項番 | ルール |
---|---|
1 | アクセス修飾子を利用できない |
2 | stract修飾子を利用できない |
3 | abstract修飾子、final修飾子を利用できる |
4 | 外側のクラスのメンバを利用できる |
5 | 外側のクラスのメソッドの引数およびローカル変数にアクセスするには、各変数がfinalでなければならない |
class outer { // 外側のクラス public void methodA(){ class local {} // ローカルクラス } }
ルール①アクセス修飾子を利用できないについて、ローカルクラスの有効範囲はメソッド内に限られるということだけ覚えておけば、「全てのクラスからの参照を許す」publicや、「他パッケージからのアクセスを制限する(同一パッケージであれば参照を許してしまう)」protectedを付けるような有効範囲外からのアクセスも許容するような設定はできないと考えれば、感覚的に覚えやすい。問題としてはローカルクラスにpublicなどが付いていれば、問答無用で該当行でコンパイルエラーとなる。
ルール②stract修飾子を利用できないについてもルール①と同様に、ローカルクラスの有効範囲はメソッド内に限られるということを覚えておけば理解しやすい。そもそもstatic修飾子をclassに付けると、外部クラスはインスタンス生成せずにstaticメンバにアクセスすることができるようになる。これをローカルクラスに無理やり当てはめた場合、「staticを付けたローカルクラスのstatic変数に外部からアクセスできる」というローカルクラスの有効範囲はメソッド内に限られるの原則を無視しなければいけなくなる。こちらも感覚的に理解しやすいのではないだろうか。こちらも問題としては、ローカルクラスにstaticが付いていれば該当行でコンパイルエラーである。
ルール③abstract修飾子、final修飾子を利用できる、ルール④外側のクラスのメンバを利用できるについても、ローカルクラスの有効範囲はメソッド内に限られる以外は特に制限がないことを踏まえると覚えやすい。普通のクラスにできることはできるのだ。ただ有効範囲に制限があるだけで……まぁ、その制限による影響があまりに大きいのだが。
ルール⑤各変数がfinalでなければならない
ローカルクラスとは、クラス内に定義されたメソッド内で定義したクラスであるが、ルール④より外側のクラスで定義されたメンバにアクセスすることが可能だ。ただし、メソッドの引数やローカル変数を扱う際には、特別なルール各変数がfinalでなければならないが存在する。
/* ルール④例 */ class outer { // 外側のクラス private static int a = 1; // 外部クラスのメンバ1 private int b = 1; // 外部クラスのメンバ2 public void methodA(){ class local { // ローカルクラス System.out.println(a); System.out.println(b); } } }
/* ルール⑤例 */ class outer { // 外側のクラス public void methodA(int a){ int b = 2; class local { // ローカルクラス System.out.println(a); System.out.println(b); // a = 100; コンパイルエラー // b = 100; コンパイルエラー } } }
上記のルール⑤例を参照して欲しい。ルール④例と異なりメソッドの引数 a とメソッドのローカル変数 b の2つにアクセスしている。System.out.printlnを用いて表示は行えるが、それぞれの変数に再代入しようとするとエラーが起きるようだ。
まとめ
ローカルクラスについて、下記2点を覚えておけば何とかなりそう。
- ローカルクラスの有効範囲はメソッド内に限られる
- 外側のクラスのメソッドの引数およびローカル変数にアクセスするには、各変数がfinalでなければならない