2010-03-20 54 views
3

我有以下代碼。這是「正確的」,哪些我不明白:爲什麼我的對象看到構造函數中沒有賦予的變量?

private static void updateGUI(final int i, final JLabel label) { 
    SwingUtilities.invokeLater( 
     new Runnable() { 
      public void run() { 
       label.setText("You have " + i + " seconds."); 
      } 
     } 
    ); 
} 

我創建了Runnable類的新實例,然後在這種情況下的run方法我用變量labeli。它有效,但我不明白它爲什麼起作用。爲什麼被考慮的對象會看到這些變量的值。

按照我的理解的代碼應該看起來像(和它的錯誤):

private static void updateGUI(final int i, final JLabel label) { 
    SwingUtilities.invokeLater(new Runnable(i,label) { 

     public Runnable(int i, JLabel label) { 
      this.i = i; 
      this.label = label; 
     } 

     public void run() { 
      label.setText("You have " + i + " seconds."); 
     } 

    }); 
} 

所以,我會給ilabel變量來構造這樣的對象可以訪問它們...

順便說一句,在updateGUI我使用finalilabel之前。我想我使用了final,因爲編譯器想要。但我不明白爲什麼。

+0

相關問題:http://stackoverflow.com/questions/1950807/anonymous-inner-classes-inside-methods – missingfaktor 2010-03-23 17:40:34

回答

2

編譯器爲你做這個工作(因爲你不能在匿名類中有構造函數)。這背後的理由是,label是在內部類的知名度。您可以訪問對象的字段或創建非匿名的內部類,它們也可以訪問最終的參數和局部變量。

2

因爲inner class可以看到外部類的所有變量。 第二個例子的問題是Runnable接口的實現者應該有一個沒有參數的構造函數。

4

final在封閉方法中聲明的變量可以被該方法中的匿名內部類訪問。如果你想使參數不是最終的,你會看到編譯器抱怨。

你不能在一個匿名的內部類中聲明一個構造函數。人們解決,有時通過寫初始化語句塊

new Runnable() { 
    { /* this code is executed */ } 

    public void run() { 
    // ... 
    } 
}; 

我覺得不能夠訪問非final變量的理由是,因爲如果您創建匿名內部類對象,然後將改變非最終變量 - 匿名內部類應該使用更新後的值嗎?當函數終止執行並且變量被銷燬時,它如何管理這種情況?如果它只能使用最終變量,則語義是明確的:它將獲取最終變量值的快照。

+0

確實,理由是updateGUI方法可能會在Runnable對象被銷燬之前終止。 – 2010-03-20 19:05:32

+1

實際上,最終變量的值作爲額外的隱藏參數傳遞給內部類構造函數,並且它們由內部類存儲在隱藏(最終)屬性中。如果您使用'javap'查看字節碼,可以看到這一點。 – 2010-03-21 00:47:19

+0

@Stephen,很好。感謝您的提示。 – 2010-03-21 02:17:46

相關問題