2012-11-03 42 views
1

所以我有一個JList和我試圖使用它JButton小號actionPerformed方法裏面,它要求我做出JListfinal這是爲什麼,下面的代碼片段內部JButton的actionperformed所需的最終變量?

public SomeClass() {  
    btnNewButton.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
     list.clearSelection();    
    }}); 
} 

我不實際上有一個問題使其最終,我只是不知道爲什麼我需要。

+1

關於這個你可以在這裏閱讀[http://support.quest.com]/questions/1299837 /無法引用非最終變量內部類定義的差異) – CAMOBAP

回答

6

要回答您的問題,您需要了解基本知識,以瞭解JVM如何使用。 當編譯包含內部類的類時,生成的字節代碼實際上並未將內部類實現爲類內的類。

爲什麼錯誤:局部變量是從一個內部類訪問,需要聲明它最終

import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import javax.swing.JMenu; 
import javax.swing.JPanel; 

public class foo extends JPanel 
{ 
    public foo() 
    { 
    final JMenu edit = new JMenu(); 
    edit.getItem(0).addMouseListener(new MouseAdapter(){ 
    @Override 
     public void mouseClicked(MouseEvent e) 
     { 
      if (e.getClickCount() == 1) { 
       edit.getItem(0).setEnabled(true); 
      } 
     } 
    }); 
    } 
} 

當您編譯這個程序,兩個文件將被創建,讓Foo.class和Foo $ 1.class。所以現在你的問題出現了,因爲Second類即foo$1.class不知道Variable編輯存在於First類內,即foo.class

那麼如何解決這個問題呢? JVM做的是,它要求開發者將外部類的變量聲明爲最終的

現在,這個正在做,現在JVM悄悄地設有第二編譯的類文件中的名稱VAL $編輯一個隱藏的變量,這裏是輸出從javap

輸出繼電器得到了讓Foo.class

C:\Mine\JAVA\J2SE\folder>javap foo.class 
Compiled from "foo.java" 
public class foo extends javax.swing.JPanel { 
    public foo(); 
} 

現在,編輯對構造函數是本地的,因此輸出如上。

C:\Mine\JAVA\J2SE\folder>javap foo$1.class 
Compiled from "foo.java" 
class foo$1 extends java.awt.event.MouseAdapter { 
    final javax.swing.JMenu val$edit; 
    final foo this$0; 
    foo$1(foo, javax.swing.JMenu); 
    public void mouseClicked(java.awt.event.MouseEvent); 
} 

Variable VAL $編輯分配已分配給編輯,因爲現在的編譯器知道,因爲它已經被聲明爲final的價值不能被改變,因此它的工作原理是相同時間值。

現在,如果我改變編輯VariableLocal到被Instance。現在,該類的對象知道有關此變量的所有內容編輯,如果它發生變化。因此,改變上述程序同樣可以得到:

import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import javax.swing.JMenu; 
import javax.swing.JPanel; 

public class foo extends JPanel 
{ 
    JMenu edit = new JMenu(); 

    public foo() 
    { 
     edit.getItem(0).addMouseListener(new MouseAdapter(){ 
     @Override 
      public void mouseClicked(MouseEvent e) 
      { 
      if (e.getClickCount() == 1) { 
        edit.getItem(0).setEnabled(true); 
       } 
      } 
     }); 
    } 
} 

在這裏,在這種情況下,我們並不想聲明,並把它定義爲final,因爲在這種情況下,因爲Variable是局部到整體類中,Variable被髮送到內部類與Object Referencethis

C:\Mine\JAVA\J2SE\folder>javap foo.class 
Compiled from "foo.java" 
public class foo extends javax.swing.JPanel { 
    javax.swing.JMenu edit; 
    public foo(); 
} 

這裏沿着是Variable是如何在這種情況下,即發送此$ 0:

C:\Mine\JAVA\J2SE\folder>javap foo$1.class 
Compiled from "foo.java" 
class foo$1 extends java.awt.event.MouseAdapter { 
    final foo this$0; 
    foo$1(foo); 
    public void mouseClicked(java.awt.event.MouseEvent); 
} 

據我看來,似乎這種解釋,這種情況是如何起作用的。 剛纔我在互聯網上找到了關於Mystery of Accessibility in Local Inner Classes的這個精彩的解釋,可能這會幫助你更好地理解情況:-)

+0

如果可以的話,我會提供+10。很好的解釋。 –

2

您正在創建一個匿名類,並且list變量的範圍太有限,因此您無法訪問它。除非你使它成爲final或使其成爲SomeClass的字段。

this article更多的一些信息

2

通過使list變量final,他們是不是真的變裁判了,但常數。然後,編譯器就可以用匿名類中的list代替常量的值(當然在編譯時),而且不會再有訪問不存在的變量的問題。