インナークラスについて質問させてください。
↓のようにインナークラスからメソッドの引数、あるいはメソッド内のローカル変数に
アクセスしようとした場合は、nnはOK。ppはNG(コンパイルエラー)っていうのが
よくわかりません。
public class NormalClass {
void test(final int nn) {
int pp= 5;
class inner {
void showResult() {
System.out.println(result = + pp); ←NG
System.out.println(result = + nn); ←OK
}
}
new inner().showResult();
}
}
文法的には、int ppにfinalをつければ通りますが
これがfinalでなければいけない理由ってなんでしょうか。
どなたかご教授ください。
finalを指定する必要が無い場合、
インナークラスがppを参照したら
そのときのppの値が表示されることを期待すると思います。
Object test() {
int pp= 5;
class Inner {
String toString() { return String.valueOf(pp); }
}
Inner inner = new inner();
System.out.println(inner); // 5と表示
pp = 10;
System.out.println(inner); // 10と表示
pp = 100;
return inner;
}
ですが、次のようにppよりInnerオブジェクトの寿命が
長い場合困ってしまいます。
void test2() {
Object inner = test();
System.out.println(inner); // もうppは存在しないのに何を表示するの?
}
そのため、
Innerクラスはppへの参照を保持するのではなく、
Innerクラスを宣言した時点でのppの値を保持するという仕様が採用されています。
#これ以外にも、ppへの参照を保持することにすれば、
#Javaには存在しない「変数の参照」機能を盛り込むことになり、
#それは無理だという理由もあります。
この仕様を採用すると、
上記リストでは常に5が表示されることになりますが、
これはプログラマを混乱させます。
そのため、finalを指定しなければならないと決められているのです。
漠然とした質問を書いてしまったなと思っていたのですが
すごく丁寧でわかりやすいご説明をして頂いて感謝しています。
// もうppは存在しないのに何を表示するの?
↑が、目から鱗でした。ほんとにおっしゃるとおりです。
メソッドを抜けてもインナークラスの参照を保持している場合が
あるので、クラスのメンバと、finalで指定されている変数しかアクセスできなくしてい
る訳ですね。