代码之家  ›  专栏  ›  技术社区  ›  HoLyVieR

当一个方法中有最终值和内部类时,究竟发生了什么?

  •  11
  • HoLyVieR  · 技术社区  · 15 年前

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

    public void method() {
        final EventHandler handle = someReference;
    
        Thread thread = new Thread() {
            public void run() {
                handle.onEvent();
            }
        };
    
        thread.start();
    }
    

    编辑: 只需意识到我的问题并不是针对我想知道的。它更多的是“如何”工作,而不是“为什么”。

    4 回复  |  直到 15 年前
        1
  •  7
  •   Piotr    15 年前

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

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

    你会得到 Test.class 对于 Test.java Test$1.class 对于内部类 爪哇 . 反编译后 测试$1类 你会看到这个:

    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 手柄 被复制为 val$handle field to the inner class. And this will work correctly only if the 手柄 永远不会改变——这在Java中意味着它必须是 final .

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

        2
  •  9
  •   cristis    15 年前
        3
  •  8
  •   Pontus Gagge    15 年前

    No method can access local variables of other methods. This includes methods of anonymous classes as the one in your example. 也就是说, run 匿名线程类中的方法,无法访问的局部变量 method() .

    写作 final 在局部变量前面是作为程序员让编译器知道变量实际上可以作为一个值来处理的一种方法。因为这个变量(读取值!)不会改变,可以用其他方法访问它。

        4
  •  2
  •   Jörn Horstmann    15 年前

    这个内部类被翻译成类似于:

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

    由于内部类实际上得到了最终变量的一个副本,因此它不能对其进行任何在外部类中可见的更改。若要禁止,即使尝试更改此参数,也只允许访问内部类中的最终变量。

    推荐文章