4

final私はそれが変数に適用されたときに変数を別のものに再割り当てすることを可能にしないキーワードであることを知って育ちました。「変数が最終的な場合、それは定数です」は多くの要約であり、私はその定義のファンではありませんが、概念を念頭に置いておくのはおそらく良い方法です. 私はそれを言いたいだけですyou cannot change the value of the variable(「値」が何を意味するにせよ)。

私の人生は幸せでしたが、ある日、私はもっと深く見てみましたmethod local inner classes...

メソッド内で定義された内部クラスは、メソッド自体で定義された変数にアクセスできません。なんで?クラスがヒープに存在し、メソッドが完了した後も存在し続ける可能性があるため (クラスの有効な参照が渡され、別の場所に格納される可能性があります)、それらの変数はスタックに存在し、メソッドが戻ると消滅します。内部クラスが存在しない変数に後でアクセスしようとするのは望ましくありません。

完全。それは理にかなっている。優秀な!そして、これらの変数を final と宣言しない限り.....そうすれば、クラスはそれらにアクセスでき、コンパイラはあなたを地獄に送りません...

WHY???つまり、これはどんな魔法ですか?final は正確には何をするのでしょうか? また、メソッド ローカル 内部クラスについて説明するのを待たなければならなかったのはなぜですか? 最終的な変数がどこに定義されていても Heap に格納されると仮定すると、メソッドのローカル内部クラスを幸せにするという概念以外に他のアプリケーションはありますか?

4

5 に答える 5

6

「最後のキーワードの最後の言葉」から引用:

この制限の理由 [ローカル クラスは、final と宣言されたローカル変数とパラメーターのみを参照できます] は、ローカル クラスがどのように実装されているかを明らかにすると明らかになります。コンパイラは、クラスが使用する各ローカル変数のコピーを保持するプライベート インスタンス フィールドをクラスに自動的に与えるため、匿名ローカル クラスはローカル変数を使用できます。また、コンパイラは、各コンストラクターに隠しパラメーターを追加して、これらの自動的に作成されたプライベート フィールドを初期化します。したがって、ローカル クラスは実際にはローカル変数にアクセスするのではなく、ローカル変数の独自のコピーにアクセスするだけです。これが正しく機能する唯一の方法は、ローカル変数が final と宣言されている場合であり、変更されないことが保証されます。この保証があれば、

于 2012-05-25T14:39:11.997 に答える
4

あなたが言及している状況では、奇妙な状況に陥る可能性があります。メソッドで内部クラスを作成すると、その内部クラスのスコープは、メソッド呼び出しの有効期間を超えて存続できます。では、内部クラスがメソッド自体の中でのみ定義されている変数を参照できるようにすると、メソッドが完了するとどうなるでしょうか?

例えば:

public void doSomethingLater()
{
  int value = 13;

  Thread t = new Thread(new Runnable() { 
    @Override public void run() {
      System.out.println("The value is " + value);
    }
  });
  t.start();

  value = 25;
}

それが許容可能な Java コードであると仮定します。そのプログラムは、実行時に何を出力しますか? 13? 25? メソッド ローカル変数への内部クラス アクセスを実装するために、Java 設計者は、内部クラスの作成時に変数の値をコピーするという単純な方法を取ることにしました。値がコピーされたことをJavaプログラマーに十分に明確にするために、最終参照を使用することを強制して、メソッドが将来の時点でその変数を変更できないようにします(新しい値が影響を与えると予想する開発者を混乱させる可能性があります)内部クラス)。

実際には、これはフードの下で起こっていることです:

public void doSomethingLater()
{
  int value = 13;

  Thread t = new Thread(new Runnable() { 
    private final _innerValue = value;
    @Override public void run() {
      System.out.println("The value is " + _innerValue);
    }
  });
  t.start();

  value = 25;
}

したがって、後で value を変更しても内部クラスには影響しないことがわかります。

アップデート:

まあ、@pgras が私を打ち負かしたと思います。とにかく、これはその回答に含まれる引用の例です。

于 2012-05-25T14:40:22.527 に答える
1

Java では、final文字通り「変数が final の場合、それは定数である」という意味ですが、多くの人がそれを意味すると考えているわけではありません。

プリミティブでは、それは本当にそれを意味します。ただし、finalオブジェクトの場合、変数が参照するオブジェクト インスタンスを変更することはできません。ただし、そのオブジェクトを必要なだけ変更することは完全に許可されています。

そのため、メソッドのローカル内部クラスでは、参照する変数を宣言する必要がありますfinal。それらが最終的に宣言されていることは、メソッドがそれらの変数が参照するオブジェクトを変更できないことを保証します。これは、メソッドの内部クラスが適切に機能するために必要な保証です。

また、ヒープとスタックについて話しているとき、変数とオブジェクトを混同しています。オブジェクトを参照するメソッド ローカル変数はスタック上に存在しますが、それらが参照するオブジェクトはヒープ上に存在します。したがって、オブジェクトのインスタンスはメソッドのスコープ外に存在するため、メソッドがスコープ外に出た場合でも、内部クラスはこれらのオブジェクトを参照し続けることができます。

于 2012-05-25T14:33:16.697 に答える
0

実際には、次の複製です:別のメソッドで定義された内部クラス内の非最終変数を参照することはできません

この回答を参照してください: https://stackoverflow.com/a/1299889/277683

スタックなどはご理解いただけたようですので、手短に。要約すると、参照を作成すると、コンパイラはコンパイル時finalにその値を安全に決定し、同じものを内部クラスに使用できます。

于 2012-05-25T14:37:56.507 に答える
0

答えははるかに簡単です。

Java 開発者 (Java を作った人) は、内部クラスで final でない変数にアクセスできると混乱するだろうと考えたので、混乱を避けるために変数が final でなければならないという要件を追加しました。

Javaがこれをどのように実装しているか正確にはわかりませんが、内部クラスが作成されるときに変数をコピーするだけだと思います。final 以外の変数でも簡単に実行できますが、Java 開発者は混乱を招くと考えていました。

于 2012-05-25T14:41:37.347 に答える