0
private final  List<KeyListener> keyListeners= new CopyOnWriteArrayList<KeyListener>();

public void addKeyListener(KeyListener keyListener){
  keyListeners.add(keyListener);
}

上記のコードでは、keyListeners が final であると宣言しており、スレッドセーフでもあります。最終的には、構築後にリスナーの状態を変更できないことを意味します。しかし、私は addKeyListener() メソッドで同じことをしていませんか? コンパイラが警告を表示しないのはなぜですか? ここで何が欠けていますか?

4

3 に答える 3

5

finalキーワードを追加すると、プログラム全体keyListenersで同じものを指すことになります。CopyOnWriteArrayList次のことを行うのは違法です。

keyListeners = null

ただし、 のメソッドはkeyListeners引き続き自由に呼び出すことができます。それらが基礎となるデータ構造に影響を与えるかどうかは、コンパイラーが気にするものではありません。


class Foo {
    public int bar = 1;

    public static void test() {
       final Foo x = new Foo();

       //This is perfectly legal:
       x.bar = 2;

       //This is not:
       x = new Foo();
    }
}
于 2012-07-06T10:02:17.763 に答える
3

final キーワードは、変数が 1 回しか割り当てられないことを示すために使用されます。ただし、オブジェクトのプロパティを「変更」する場合でも、メソッドを呼び出すことができます。

JLSから:

最終変数が割り当てられると、常に同じ値が含まれます。最終変数がオブジェクトへの参照を保持している場合、オブジェクトの状態はオブジェクトに対する操作によって変更される可能性がありますが、変数は常に同じオブジェクトを参照します。

于 2012-07-06T10:05:01.297 に答える
0

最終的には、リスト自体ではなく、keyListeners の内部アドレスを参照するためです。

于 2012-07-06T10:01:58.613 に答える