Java : ローカルクラスがfinalなローカル変数しかアクセスできない理由
Javaがローカルクラスの仕様を決めたとき、ローカル変数をわざわざfinalな変数に絞ったのには、なにか合理的な理由があるはずだと思うので、それを推測するコーナー。(あくまでも「推測」なので、証拠を出せとか言われても困ります。)
-
-
- -
-
まず、ローカル変数がスタック上に取られるからという案は、却下です。サンデープログラマが趣味で書いた処理系でもあるまいし、そんなことが技術的な制限になるとはちょっと考えられない。
-
-
- -
-
前提として留意しておきたいのは、Javaが構文糖衣に対して非常に保守的だということ。理由はよく分かりませんが、とにかく新しい構文糖衣を導入することに対して、慎重なようです。想像するに、構文糖衣というものに対して、プログラマから見えないところで直感的でない変換が行われることがあるため、プログラムの不確実性が増して、分かりづらいバグの温床になる、というような考え方があるのじゃないかな?(あくまで想像ですよ)
-
-
- -
-
それから、プログラマがポインタ概念を意識する必要がないように言語仕様が作られているということがあります。こういう話になるとJavaにはポインタがあるよということを説明したがる向きもいるかもしれませんが、それはあくまで実装的な話であって、Javaプログラマが、それがポインタであることを利用してなにかやる(端的にはポインタ演算を行う)ことはできないようになっています。*1
また、ポインタ概念がないということは、C++でいうところの参照がないということでもあります。(代わりに、Delphiの引数のvar渡しのことを思い浮かべてもらってもかまわないかと思います。)この参照がないということが、ローカルクラスがfinalなローカル変数にしかアクセスできない理由なのではないかとにらんでいます。
つまり、以下のコードで更新された n にアクセスできるということは、暗黙的に変数 n の参照が作成されていると考えられるわけで、ポインタの概念を持たない以上、それを破綻なく説明することは無理ということなのではないかと思います。
interface Counter { int get();} class OuterClass { int useCounter(int n) { counterUsingMethod( new Counter() { int get() { return n++;}}); return n; } }
*1:関数やgoto, breakのラベルが、実体はポインタ(アドレス)であっても、そのことを持ってポインタ概念があるとは言わないのと同じです。