11

I have came across many situation where I needed to pass value to an other thread and I founded out that I could do it this way, but I have been wondering how is it working ?

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

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

    thread.start();
}

Edit: Just realise my question wasn't exactly pointing toward what I wanted to know. It's more "how" it works rather then "why".

4

4 回答 4

9

下面是它如何工作的更长解释:http: //techtracer.com/2008/04/14/mystery-of-accessibility-in-local-inner-classes/

于 2010-06-26T20:32:47.600 回答
8

没有方法可以访问其他方法的局部变量。这包括匿名类的方法,例如您的示例中的方法。即run匿名 Thread 类中的方法,无法访问method().

final在局部变量前面是程序员让编译器知道变量实际上可以被视为值的一种方式。由于这个变量(读取值!)不会改变,所以在其他方法中访问它是“可以的”。

于 2010-06-26T20:30:40.747 回答
7

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

编译这段代码后:

public class Test {

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

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

     thread.start();
 }
}

您将获得Test.classforTest.javaTest$1.classfor 中的内部类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();
  }
}

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

您还可以注意到内部类有一个字段this$0是对外部类的引用。这反过来又显示了非静态内部类如何能够与外部类进行通信。

于 2010-06-26T20:51:11.547 回答
2

这个内部类被翻译成类似于以下的代码:

class InnerClass extends Thread {
    private EventHandler handle;

    public InnerClass(EventHandler handle) {
        this.handle = handle;
    }

    public void run() {
        handle.onEvent();
    }
}

...

EventHandler handle = someReference;
Thread thread = new InnerClass(handle);
thread.start();

由于内部类实际上传递了最终变量的副本,因此无法对其进行任何在外部类中可见的更改。为了禁止甚至尝试更改此参数,它只允许访问内部类中的最终变量。

于 2010-06-26T20:43:18.877 回答