2

int i次の例では、パラメーターを次のように設定して動作し、コンパイルします。final

class Miner1
{
    Miner getMiner(final int i) {
        return new Miner() {                
           public void perform_work() { 
              System.out.println(i);
           }
        };
    }

interface Miner { void perform_work(); }

それ以外の場合、前の例のように final に設定されていない場合、コンパイルされません。理由を知っている人はいますか?final中括弧がまだ閉じられていないため、なくても範囲内にある必要があります。

前もって感謝します。

4

4 に答える 4

4

これはスコープではなく、匿名の内部クラスで行われます。

親クラスで宣言されている匿名クラスからローカル変数にアクセスすることはできませんが、変数がfinal.

ロジックを説明するSOに関するこの他の質問を見てください。

于 2013-03-07T11:07:40.350 に答える
3

範囲とは関係ありません。

Java では、匿名クラスは、スコープ外の変数のみを参照できますfinal

JLSから:

内部クラスで宣言されていないローカル変数、仮パラメーター、または例外パラメーターは、宣言する必要がありますfinal

于 2013-03-07T11:06:34.933 に答える
2

Java では、メソッド/コンストラクター内で定義された匿名クラスから参照できるのは、最終的な変数/引数のみです。これは、コードの動作をより直感的にするためです。変数/引数の値は、インスタンスの作成時に隠しコンストラクター引数を介して匿名クラスのインスタンスに渡されるため、匿名クラスのインスタンスは変数のそれ以上の変更を追跡できません。final 以外の変数へのアクセスが許可される場合は、次のように記述できます。

int a = 5;

Thread t = new Thread ()
{
    @Override
    public void run ()
    {
        System.out.println (a); // This will print 5, rather than 6!
    }
};

a = 6;

t.start ();

そして、6印刷されることを期待してください。上記のコードが を出力する理由を理解するために、5このコードは次のコードと同等であることに注意してください。

class MyThread extends Thread
{
    int _a;

    public MyThread (int a)
    {
        this._a = a;
    }

    @Override
    public void run ()
    {
        System.out.println (_a);
    }
}

int a = 5;

Thread t = new MyThread (a); // Value `5` is passed

a = 6;

t.start (); // Value `5` passed to the constructor earlier is printed here
于 2013-03-07T11:08:59.720 に答える
0

これは、Java では匿名内部クラスが final ローカル変数とクラスのフィールドにしかアクセスできないためです。
今問題はなぜですか?
これは、メソッドのローカル変数(getMinerあなたの場合)がスタック上に存在し、メソッドの存続期間のみ存在するためです。ローカル変数のスコープは、変数が宣言されている同封のメソッドに限定されます。メソッドが終了すると、スタック フレームは吹き飛ばされ、変数は履歴になります。ただし、メソッドが完了した後でも、メソッド内で作成された内部クラス オブジェクトはヒープ上に残っている可能性があります。たとえば、匿名の内部クラスの参照がMiner取得された場合getMinerコードの別の場所に渡され、そこで使用されます。ローカル変数はすでに爆破されているため、そのオブジェクトにとっては奇妙な状況になります。この問題の解決策の 1 つは、匿名内部クラス オブジェクトがローカル変数のコピーを作成することです。ただし、ローカル変数は変更の影響を受けやすいため、匿名の内部クラス オブジェクトがその変数の最新の値を参照できることは保証されません。

ただし、ローカル変数が final の場合、初期化後に変数値がどのような条件でも変更されないことが保証されるため、メソッドローカル内部クラスは、元の値の後でも存在するプライベート使用のためにそのコピーを作成できます。スタックから削除されました。

于 2013-03-07T11:24:51.460 に答える