2011-04-13 142 views
18

編譯我的代碼後,我得到了兩個錯誤。局部變量訪問內部類(java)

的錯誤是:

local variable input is accessed within inner class; 
    needs to be declared final 
    String name = input.getText(); 

2.

local variable c_age is accessed within inner class; 
    needs to be declared final 
    Object child_age = c_age.getSelectedItem(); 

這是我的代碼:

import javax.swing.*; 
import java.awt.event.*; 

public class GUI 
{ 
    public static void main(String[] args) 
    { 
     JFrame frame = new JFrame("Try GUI"); 
     JLabel l1 = new JLabel("Please Enter Your Child's Name"); 
     JTextField input = new JTextField("",10); 

     JLabel l2 = new JLabel("Choose Your Child's Age"); 
     String[] age = {"Age","1","2","3","4","5","6"}; 
     JComboBox c_age = new JComboBox(age); 

     JButton button = new JButton("Search"); 

     JTextArea result = new JTextArea(); 
     JScrollPane extend_area = new JScrollPane(result); 

     button.addActionListener(new ActionListener() 
     { 
      public void actionPerformed(ActionEvent ae) 
      { 
       String name = input.getText(); 
       Object child_age = c_age.getSelectedItem(); 
      } 
     }); 

     JPanel panel = new JPanel(); 
     panel.add(l1); 
     panel.add(input); 
     panel.add(l2); 
     panel.add(c_age); 
     panel.add(button); 
     panel.add(extend_area); 
     frame.add(panel); 
     frame.setSize(350,350); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setVisible(true); 
    } 

} 

我該如何解決這個錯誤?

回答

16

需要聲明

JTextField input = new JTextField("",10); 

JComboBox c_age = new JComboBox(age); 

這樣的:

final JTextField input = new JTextField("",10); 

final JComboBox c_age = new JComboBox(age); 

這意味着inputc_age不能改變:

Any local variable, used but not declared in an inner class must be definitely assigned before the body of the inner class.

解釋從Java語言規範採取Section - 8.1.3 Inner Classes and Enclosing Instances

+0

問題解決了,但我不明白你的解釋。你可以給更多的...非常感謝Edward – Roubie 2011-04-13 04:32:01

+0

附加了一個摘錄和鏈接到Java語言規範,我希望這有助於... – edwardsmatt 2011-04-13 04:34:40

+3

final是需要的,以便用戶內部類/閉包使用它時,不能更改該變量。想一想:如果它沒有標記爲final,那麼內部類引用可以完成聲明旁邊的所有代碼,因此必須將其標記爲final以避免併發性問題,並且語法會強制執行此操作。 – 2011-04-13 05:05:45

0

名爲input的JTextField在main方法內聲明。你應該這樣做:

public class GUI{ 

     //declare all your components here e.g. 

     JTextField input; 

     public static void main(String args[]){ 
       new GUI(); 
     } 

     public GUI(){ 
      //instantiate components here 
      input = new JTextField(); 
      //and so on. 
     } 

    } 

這樣,內部類的輸入引用將不會產生任何問題。

+0

我有這個錯誤:非靜態變量不能從靜態上下文中引用 – Roubie 2011-04-13 04:41:05

+0

主要方法是靜態上下文。你必須通過實例化你的類的一個實例來打破它,就像我的例子。然後,你的主要方法中的各種代碼應該在構造函數中進行。 – 2011-04-13 04:46:27

0

您必須聲明final兩個變量你accesing:inputc_age

如果你不想這樣做,那麼你可以創建一個新的適當的類(不是臨時的),並在構造函數中將這些參數作爲參數傳遞,或者(我在GUI中使用Java)創建一個監聽器類,它在構造函數中使用對象並使它們在本地可用,然後ad-hoc實例化它。

2

您在內部類的actionPerformed方法中使用的任何變量都需要聲明爲final。請嘗試以下操作:

import javax.swing.*; 
import java.awt.event.*; 

    public class GUI 
    { 
     public static void main(String[] args) 
     { 
      JFrame frame = new JFrame("Try GUI"); 
      JLabel l1 = new JLabel("Please Enter Your Child's Name"); 
      final JTextField input = new JTextField("",10); 

      JLabel l2 = new JLabel("Choose Your Child's Age"); 
      String[] age = {"Age","1","2","3","4","5","6"}; 
      final JComboBox c_age = new JComboBox(age); 

      JButton button = new JButton("Search"); 

      JTextArea result = new JTextArea(); 
      JScrollPane extend_area = new JScrollPane(result); 

      button.addActionListener(new ActionListener() 
      { 
        public void actionPerformed(ActionEvent ae) 
        { 
         String name = input.getText(); 
         Object child_age = c_age.getSelectedItem(); 


        } 
      }); 

      JPanel panel = new JPanel(); 
      panel.add(l1); 
      panel.add(input); 
      panel.add(l2); 
      panel.add(c_age); 
      panel.add(button); 
      panel.add(extend_area); 
      frame.add(panel); 
      frame.setSize(350,350); 
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      frame.setVisible(true); 
     } 

    } 
+0

你能解釋爲什麼需要聲明它是最終的嗎? – Seth 2014-03-18 01:29:31

0

在方法執行完成後,輸入變量和c_age變量消失。你不會被允許在本地內部類中使用這些變量,除非它是最終的。

5

If you declare the variables as an final then it will solve your errors but according to me its not the good solution for the problem. Similar problem has discussed here you can have a look here for more understanding.

In solution to yours problem you can have define methods by using them you can get better solution. For hint you can read How to access non-final local variable inside anonymous inner class

+0

以其他方式,您可以將輸入和c_age變量聲明爲靜態實例變量,以解決您的問題。 – 2011-04-13 05:15:12

0

我剛剛在主類中創建了一個臨時變量,例如'tempString',然後它可以設置爲導致問題的變種。所以:

tempString = myString 

這樣我可以調用tempString沒有任何問題。檢查下面我舉的例子:

// Create my temp var here 
private String tempUrl; 

// my function here 
public void updatePage(String url) 
{ 
    // Can use 'url' here because it's not within inner class 
    if(!url.equals("")) 
    { 
     // Set 'tempUrl' to 'url' so I can use it without problem 
     tempUrl = url; 

     // My inner class that used to cause the problem 
     backgroundUpdate = new Thread(new Runnable() 
     { 
      // From here on I use 'tempUrl' to solve the problem 
      public void run() 
      { 
       // Do something with 'tempUrl' here (where 'url' used to be used) 
      } 
     }); 

     backgroundUpdate.start(); 
    } 
} 
1

作爲添加final帶走了很大的靈活性,我想建議如下:創建訪問方法,這是無論如何鼓勵。但是,這在處理對象時最有用,而在你的情況下,一切都是靜態的。因此,這個答案可能不適用於你的具體情況,但因爲你的錯誤消息的谷歌搜索產生這個問題作爲最重要的結果,我認爲一個替代方案適用於大多數情況下(使用對象比靜態方法更常見)也應該在這裏。

public class MyClass extends MySuperClass { 
    private MyPropertyClass aProperty; 

    public MyClass() { 
     new JButton().setActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
       // aProperty.aMethod(); -- Bang! That should be final, the compiler says. 
       getMyProperty().aMethod(); // -- Everything okay, works fine, no compiler complaints. 
      } 
     }); 
    } 

    public getMyProperty() { 
     return aProperty; 
    } 
}