2010-06-26 39 views
11

我碰到过很多情况,我需要将价值传递给其他线程,并且我发现我可以这样做,但我一直在想它是如何工作的?当方法中有最终值和内部类时会发生什么?

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

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

    thread.start(); 
} 

编辑:只要知道我的问题不是正朝向什么,我想知道的指点。它更“如何”起作用,而不是“为什么”。

回答

7

您可以通过简单地反编译内部类来注意到底下会发生什么。下面是一个简单的例子:

编译这段代码后:

public class Test { 

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

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

    thread.start(); 
} 
} 

你会得到Test.classTest.javaTest$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(); 
    } 
} 

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

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

8

没有方法可以访问其他方法的局部变量。这包括您的示例中匿名类的方法。也就是说,匿名Thread类中的run方法不能访问局部变量method()

在局部变量前写入final是一种让程序员知道变量实际上可以被当作值的程序员。由于此变量(读取值!)不会更改,因此可以通过其他方法访问它。

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(); 

由于内部类实际上得到通过,也有最终的变量的副本不会对外部类中可见的任何更改进行更改。甚至不允许对该参数进行更改,只允许访问内部类中的最终变量。

相关问题