为什么Elvis Elvis定义必须是最终的,才能在Thread run()方法中使用?

 Elvis elvis = Elvis.INSTANCE; // ----> should be final Elvis elvis = Elvis.INSTANCE
 elvis.sing(4);

 Thread t1 = new Thread(
   new Runnable() {
   @Override
   public void run() {
   elvis.sing(6); // --------> elvis has to be final to compile
  }
}
);


 public enum Elvis {
   INSTANCE(2);

   Elvis() {
     this.x = new AtomicInteger(0);
   }

   Elvis(int x){
     this.x = new AtomicInteger(x);
   }

   private AtomicInteger x = new AtomicInteger(0);

   public int getX() { return x.get(); }

   public void setX(int x) {this.x = new AtomicInteger(x);}

   public void sing(int x) {
      this.x = new AtomicInteger(x);
      System.out.println("Elvis singing.." + x);
   }
 }

最佳答案

elvis变量的值被匿名内部类捕获。

仅Java(当前)按值捕获变量。编译器要求变量是最终变量,以便不会混淆在新线程中调用run方法时实际使用的内容:如果在创建新线程之后但在更改之前更改了elvis的值启动它,您希望它做什么?

这是在C#和Java中有效使用闭包的方式之间的区别。有关更多详细信息,请参见我的closures article。 Java 7将使闭包更加简洁-我一直没有跟踪了解是否有任何方法可以捕获变量本身而不是特定值。

07-24 14:42