内部クラスからアクセス可能なローカル変数が final でなければならない理由

なぜ、内部クラス(ローカルクラス、匿名クラス)からアクセス可能なローカル変数が final でなければならないのか、
その理由が次の記事に説明されている。

いまさらだけど、Java言語にはクロージャーがない - 達人プログラマーを目指して

しかし、

つまり、以下のプログラムを考えてみれば内部クラス中からアクセスするローカル変数がfinalでなくてはならない理由が納得ができます。

とあるが、残念ながら、例示されているプログラムでは納得することはできない。
以下がそのプログラム。

public Test createTest(final int param) {
    final String value = "Hello";

    // finalでないと
    // value = "Hello2";
    // param = 3;
    // などの再代入が可能で結果が矛盾する。

    return new Test() {
        public void print() {
            System.out.println("param = " + param);
            System.out.println("value = " + value);
        }
    };
}

このサンプルプログラムは return 文でインスタンス生成しているので、
インスタンス生成時以降の値の変更を防いでいるということが見えにくい。
それを見るには、以下のような例の方がよい。

public Test createTest(final int param) {
    final String value = "Hello";

    Test test = new Test() {
        public void print() {
            System.out.println("param = " + param);  // 値はコピーされる
            System.out.println("value = " + value);  
        }
    };

    // param = 3;       ← このような再代入を防ぐ
    // value = "Bye";   ← このような再代入は防ぐ

    return test;
}

リンク先で参照された記事を、ここでも紹介しておく。

Java FAQ S016 Q-14
JavaFAQ: 内部クラス - inner class

変数の参照を制限する理由が、このリンク先の記事で説明されている。
この記事では、内部クラスのインスタンスを生成する時、ローカル変数の値をコピーしてインスタンス内部に保持するのは、スタック上のローカル変数が破棄された後でも、それらのローカル変数の値を使えるようにするため、と書いており、このコピーした値が矛盾のないものとするため「参照可能なものを内部クラスが生成される時点以降に値が変更されないもの、すなわち、final宣言されているローカル変数や引数のみに制限し、」と述べている。

引用文の「内部クラスが生成される時点以降に値が変更されないもの、」がポイントである。
それで、上記のようにサンプルプログラムを変えてみたわけである。

それでも、疑い深い人は、
「じゃ、メソッドからリターンする時点での最終的な値を Test クラスのインスタンスに埋め込めばいいではないか」
と考えるかもしれない。

しかし、内部クラスのインスタンスは、当該のメソッドのなかで使用される可能性がある。
上の2番目のサンプルプログラムでいえば、Test クラスのインスタンスが生成された直後に
test.print(); とメソッドを呼び出すことが考えられる。
そのような可能性を考えれば、値のコピーは、内部クラスのインスタンス生成時点で行うのが妥当といえる。