2011-04-13 140 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; 
    } 
}