2010-06-26 21 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(); 

由於內部類實際上得到通過,也有最終的變量的副本不會對外部類中可見的任何更改進行更改。甚至不允許對該參數進行更改,只允許訪問內部類中的最終變量。

相關問題