繁体   English   中英

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

[英]What exactly happens when you have final values and inner classes in a method?

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

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

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

    thread.start();
}

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

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

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

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

编译完这段代码后:

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字段,它是对外部类的引用。 这反过来说明了非静态内部类如何与外部类进行通信。

这个内部类被转换为类似于的代码:

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM