在内部类(java)中访问局部变量

编译完代码后,我遇到了两个错误。

错误是:

1。

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); } } 

我该如何解决这个错误?

你需要申报

 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不能更改:

必须在内部类的主体之前明确地分配在内部类中使用但未声明的任何局部变量。

解释取自Java语言规范, 第8.1.3节内部类和封闭实例

如果您将变量声明为final,那么它将解决您的错误,但据我所知,它不是解决问题的好方法。 这里讨论过类似的问题,你可以看看这里有更多的了解。

在解决您的问题时,您可以通过使用它们来定义方法,您可以获得更好的解决方案。 有关提示,您可以阅读如何访问匿名内部类中的非最终局部变量

您在内部类的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); } } 

由于添加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; } } 

JTextField命名输入是在main方法内声明的。 你应该做这样的事情:

  public class GUI{ //declare all your components here eg JTextField input; public static void main(String args[]){ new GUI(); } public GUI(){ //instantiate components here input = new JTextField(); //and so on. } } 

这样,对内部类内部输入的引用将不会产生任何问题。

您必须声明final的两个变量: inputc_age

如果你不想这样做,那么你可以创建一个新的正确类(而不是ad-hoc)并将它们作为参数传递给构造函数,或者(我在使用Java中的GUI时这样做)创建一个在其构造函数中获取对象并使它们在本地可用的侦听器类,然后临时实例化该对象。

方法执行完成后,输入变量和c_age变量消失。 除非是最终的,否则不允许在本地内部类中使用这些变量。

我刚刚在主类中创建了一个临时var,例如’tempString’,然后它可以设置为导致问题的var。 所以:

 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(); } }