匿名クラスと最終フィールドに関する説明にはまだ満足していません。明らかな問題を説明しようとする質問がたくさんありましたが、すべての質問に対する答えが見つかりませんでした:-)
次のコードを想定します。
public void method(final int i, int j) {
final int z = 6;
final int x = j;
int k = 5;
new Runnable() {
public void run() {
System.out.print(i);
System.out.print(x);
System.out.print(z);
System.out.print(k);
}
};
}
- 「unfinal」
k
プロパティのため、このコードをコンパイルすることはできません。 z
コンパイル時にコンパイラがプロパティを宣言された値に置き換えることができることを理解しています。
解決策を検索したところ、正確にどのように機能するかを調べたところ、i
次のような回答がx
見つかりました。
コンパイラは、匿名クラスの lastPrice と price の使用を定数の値に置き換えるだけで (もちろんコンパイル時に)、存在しない変数にアクセスする際の問題はなくなります。
フィールドに対してどのように機能しi
、x
それらがメソッドのパラメーターである場合はどうなりますか? それらはコンパイル時に認識されませんか? このアプローチは、z
.
一方、スタックの問題に関する説明があります。
これにより、Java コンパイラは実行時に変数の値を「キャプチャ」し、コピーをフィールドとして内部クラスに格納できます。外側のメソッドが終了し、そのスタック フレームが削除されると、元の変数はなくなりますが、内側のクラスのプライベート コピーはクラス自身のメモリに残ります。
匿名クラスは、作成中に必要なすべてのコンテンツ (フィールド) を何らかの形でコピーしたことを理解しています。欠落には、匿名クラス宣言の下final
のコードが値を変更する場合、実行で可能な値が使用されるという明らかな問題があります。stale
しかし、匿名クラスのメソッドが使用されたプロパティの範囲外で実行されるとき、これは問題を解決するはずです。
ただし、このアプローチはすべてのフィールドをコピーするだけなので、宣言なしでも機能するはずです。final
どちらのアプローチも、私にとっては独立しているように見えます。そういえば - そしてそれは私の質問を解決することができます - 私はfinal
メソッドフィールドがどのように機能するかを知りませんでした. メソッドが終了してもスタックから削除されませんか? 私にはナンセンスに思えますが、それは多くのことを説明します:-)
正解は?