简体   繁体   English

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

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

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". 它更“工作”,而不是“为什么”。

No method can access local variables of other methods. 没有方法可以访问其他方法的局部变量。 This includes methods of anonymous classes as the one in your example. 这包括匿名类的方法,如示例中的方法。 That is, the run method in the anonymous Thread class, can not access the local variable of method() . 也就是说,匿名Thread类中的run方法无法访问method()的局部变量。

Writing final in front of the local variable is a way for you as a programmer to let the compiler know that the variable actually can be treated as a value. 在本地变量前写入final是一种让程序员让编译器知道变量实际上可以被视为值的方法。 Since this variable (read value!) will not change, it is "ok" to access it in other methods. 由于此变量(读取值!)不会更改,因此在其他方法中访问它是“可以的”。

You can notice what happens underneath by simply decompiling the inner class. 你可以通过简单地反编译内部类来注意下面发生的事情。 Here is a short example: 这是一个简短的例子:

After compiling this piece of code: 编译完这段代码后:

public class Test {

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

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

     thread.start();
 }
}

you will get Test.class for Test.java and Test$1.class for the inner class in Test.java . 你会得到Test.classTest.javaTest$1.class在内部类Test.java After decompiling the Test$1.class you will see this: 反编译Test$1.class你会看到:

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

  public void run()
  {
    this.val$handle.toString();
  }
}

As you can see instead of handle variable there is this.val$handle . 正如你所看到的那样,而不是handle变量有this.val$handle This means that handle is copied as a val$handle field to the inner class. 这意味着handle被复制为val$handle字段到内部类。 And this will work correctly only if the handle will never change - which in Java means it must be final . 只有当handle永远不会改变时,这才能正常工作 - 这在Java中意味着它必须是final

You can also notice that the inner class has a field this$0 which is a reference to the outer class. 您还可以注意到内部类有一个this$0字段,它是对外部类的引用。 This in turn shows how non static inner classes are able to communicate with outer classes. 这反过来说明了非静态内部类如何与外部类进行通信。

This inner class gets translated to code similar to: 这个内部类被转换为类似于的代码:

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

Since the inner class actually gets passed a copy of the final variable it can not make any changes to it that would be visible in the outer class. 由于内部类实际上传递了最终变量的副本,因此它不能对外部类中可见的任何更改。 To disallow even trying to make changes to this parameter it is only allowed to acces final variables in inner classes. 要禁止甚至尝试更改此参数,只允许访问内部类中的最终变量。

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

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