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

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

在上面的代码中,我将 keyListeners 声明为 final 并且它是线程安全的。我假设 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 关键字用于告诉变量只能分配一次。但是即使它“更改”对象属性,您也可以对其调用方法。

JLS

一旦分配了最终变量,它总是包含相同的值。如果最终变量持有对对象的引用,则对象的状态可能会通过对对象的操作而改变,但变量将始终引用同一个对象。

于 2012-07-06T10:05:01.297 回答
0

只是因为 final 引用了 keyListeners 的内部地址而不是列表本身。

于 2012-07-06T10:01:58.613 回答