当方法中有最终值和内部类时,究竟会发生啥?
Posted
技术标签:
【中文标题】当方法中有最终值和内部类时,究竟会发生啥?【英文标题】:What exactly happens when you have final values and inner classes in a method?当方法中有最终值和内部类时,究竟会发生什么? 【发布时间】:2010-06-26 20:22:37 【问题描述】:我遇到过很多需要将值传递给其他线程的情况,我发现我可以这样做,但我一直想知道它是如何工作的?
public void method()
final EventHandler handle = someReference;
Thread thread = new Thread()
public void run()
handle.onEvent();
;
thread.start();
编辑:只要意识到我的问题并不完全指向我想知道的。更多的是“如何”工作,而不是“为什么”。
【问题讨论】:
【参考方案1】:以下是对其工作原理的详细说明:http://techtracer.com/2008/04/14/mystery-of-accessibility-in-local-inner-classes/
【讨论】:
【参考方案2】:没有方法可以访问其他方法的局部变量。这包括匿名类的方法,例如您的示例中的方法。即匿名Thread类中的run
方法,无法访问method()
的局部变量。
在局部变量前面写final
是程序员让编译器知道变量实际上可以被视为值的一种方式。由于这个变量(读取值!)不会改变,所以在其他方法中访问它是“可以的”。
【讨论】:
【参考方案3】:您可以通过简单地反编译内部类来注意到下面发生的事情。这是一个简短的例子:
编译这段代码后:
public class Test
public void method()
final Object handle = new Object();
Thread thread = new Thread()
public void run()
handle.toString();
;
thread.start();
对于Test.java
,您将获得Test.class
,对于Test.java
中的内部类,您将获得Test$1.class
。反编译Test$1.class
后你会看到:
class Test$1 extends Thread
final Test this$0;
private final Object val$handle;
public void run()
this.val$handle.toString();
如您所见,this.val$handle
不是变量handle
。这意味着handle
被作为val$handle
字段复制到内部类。只有当handle
永远不会改变时,这才能正常工作——这在Java 中意味着它必须是final
。
您还可以注意到内部类有一个字段this$0
,它是对外部类的引用。这反过来又显示了非静态内部类如何能够与外部类进行通信。
【讨论】:
【参考方案4】:这个内部类被翻译成类似于以下的代码:
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();
由于内部类实际上传递了最终变量的副本,因此无法对其进行任何在外部类中可见的更改。甚至禁止尝试更改此参数,它只允许访问内部类中的最终变量。
【讨论】:
以上是关于当方法中有最终值和内部类时,究竟会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章
当我们重新启动 Azure Databricks 群集时,内部会发生啥?