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

在内部类(java)中访问局部变量,java,actionlistener,inner-classes,final,Java,Actionlistener,Inner Classes,Final,我编译代码后出现了两个错误 错误为: 1. local variable input is accessed within inner class; needs to be declared final String name = input.getText(); local variable c_age is accessed within inner class; needs to be declared final Object child_age

我编译代码后出现了两个错误

错误为:

1.

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

  local variable input is accessed within inner class; 
  needs to be declared final
     String name = input.getText();
  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);
    }

}

如何解决此错误?

名为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.
      }

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

final JComboBox c_age = new JComboBox(age);
这样,对内部类中输入的引用就不会出现问题。

您需要声明

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

像这样:

  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.
      }

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

final JComboBox c_age = new JComboBox(age);
这意味着
input
c\u age
不能更改:

任何局部变量,已使用但未使用 在内部类中声明的 在比赛前明确分配 内部类的主体


根据Java语言规范的解释,

您必须声明正在访问的两个变量:
input
c\u age


如果您不想这样做,那么您可以创建一个新的适当类(不是临时类)并将其作为参数传递到构造函数中,或者(我在Java中使用GUI时就是这样做的)创建一个侦听器类,该类接受构造函数中的对象并使它们在本地可用,然后特别实例化它。

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

    }

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

如果你将变量声明为最终变量,那么它将解决你的错误,但根据我的说法,这不是解决问题的好办法。类似的问题已经在这里讨论过了,你们可以看看,以获得更多的理解

在解决您的问题时,您可以定义方法,通过使用它们,您可以得到更好的解决方案。你可以读到一些提示


我刚刚在主类中创建了一个临时变量,例如“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();
    }
}

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

问题已解决。但我不理解您的解释。希望您能提供更多…非常感谢Edward附加了Java语言规范的摘录和链接,我希望这有帮助…需要final,以便用户在内部类/闭包使用变量时无法更改变量。想想看:如果它没有标记为final,内部类引用可以完成声明旁边的一些代码所能做的一切,因此您必须将它标记为final以避免并发问题,并且语法强制执行这一点。我有一个错误:不能从静态上下文引用非静态变量。主要方法是静态上下文。您必须通过实例化类的实例(如我的示例中所示)来打破它。然后,主方法中的各种代码应该进入构造函数。换句话说,您可以将输入和c_年龄变量声明为静态实例变量,这将解决您的问题。您能否解释为什么需要将其声明为final?