Javaで、ローカル変数にfinalを付けると、その変数は変更されないということを保障します。
では、変更しないローカル変数には全てfinalを付けるべきなのでしょうか?
今回は、必ずfinalを付けざるを得ない、以下のコードのような場合を考えてみたいと思います。
class DisplayImpl implements Display {
private JFrame frame;
public DisplayImpl(int width, int height) {
final Dimension size =
new Dimension(width, height);
// ① finalで宣言
frame = new JFrame() {
Dimension getPrefferedSize() {
return size;
// ② finalでないと参照できない
}
};
size.height = 5; // ③ OK
size = null; // ④ コンパイル・エラー
}
}
JFrameを派生した内部無名クラスからローカル変数sizeにアクセスする場合、final宣言が必要です。
これは評価のタイミングで、無名クラスが生成されるタイミングが、コードの順番どおりという訳ではないので、例えば、④のようにnullを代入してしまうと、冒頭でnewしたDimensionオブジェクトを参照していいのか、nullを代入したあとの値を参照していいのかの判断がつかないためだと思われます。
しかし、Javaではプリミティブ型以外は全て参照ですので、参照先を変更する(③のような)コードならOKなのです。
ソースコードを検査するあるツールを入れたりすると、変更していないローカル変数にfinalが付いていない旨のエラーがでることがあります(設定次第)。
そうなると、参照型のローカル変数というのは大抵、finalを付けないといけないということになってしまいます。
同じローカル変数に何度も別のオブジェクトを割り当てたり、わざわざnullを設定するようなことが少ないからです。
結論として、個人的なルールとしてはローカル内部クラスか無名内部クラスからアクセスする場合のみfinalを付けるという方針をとることにしました。
『プログラミング言語Java 第4版』P151にも、同様の意見が書かれていました。