在方法中有最终值和内部类时会发生什么?

HoL*_*ieR 11 java inner-classes

我遇到过很多需要将值传递给另一个线程的情况,我发现我可以这样做,但我一直想知道它是如何工作的?

public void method() {
    final EventHandler handle = someReference;

    Thread thread = new Thread() {
        public void run() {
            handle.onEvent();
        }
    };

    thread.start();
}
Run Code Online (Sandbox Code Playgroud)

编辑:只是意识到我的问题并没有完全指向我想知道的事情.它更"工作",而不是"为什么".

aio*_*obe 8

没有方法可以访问其他方法的局部变量.这包括作为一个在你的例子匿名类的方法.也就是说,run在匿名的Thread类的方法,不能访问的局部变量method().

final在局部变量前面编写是一种让程序员让编译器知道变量实际上可以被视为值的方法.由于此变量(读取值!)不会更改,因此在其他方法中访问它是"可以的".


Pio*_*otr 7

你可以通过简单地反编译内部类来注意下面发生的事情.这是一个简短的例子:

编译完这段代码后:

public class Test {

 public void method() {
     final Object handle = new Object();

     Thread thread = new Thread() {
         public void run() {
             handle.toString();
         }
     };

     thread.start();
 }
}
Run Code Online (Sandbox Code Playgroud)

你会得到Test.classTest.java,并Test$1.class在内部类Test.java.反编译后Test$1.class你会看到:

class Test$1 extends Thread
{
  final Test this$0;
  private final Object val$handle;

  public void run()
  {
    this.val$handle.toString();
  }
}
Run Code Online (Sandbox Code Playgroud)

你可以看到而不是handle变量this.val$handle.这意味着handle将其作为val$handle字段复制到内部类.只有当它handle永远不会改变时,这才能正常工作- 这在Java中意味着它必须是final.

您还可以注意到内部类有一个字段this$0,它是对外部类的引用.这反过来说明了非静态内部类如何与外部类进行通信.