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

时间:2011-04-13 04:17:36

标签: java actionlistener inner-classes final

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

错误是:

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

}

如何解决此错误?

8 个答案:

答案 0 :(得分: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无法更改:

  

使用但未使用的任何局部变量   在内部类中声明必须是   绝对分配之前   内心阶级的身体。

来自Java语言规范的解释,Section - 8.1.3 Inner Classes and Enclosing Instances

答案 1 :(得分:5)

  

如果您将变量声明为final,那么它将解决您的错误,但据我所知,它不是解决问题的好方法。此处讨论了类似的问题,您可以查看here以获得更多理解。

     

在解决您的问题时,您可以通过使用它们来定义方法,您可以获得更好的解决方案。提示你可以阅读   How to access non-final local variable inside anonymous inner class

答案 2 :(得分: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);
        }

    }

答案 3 :(得分: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;
    }
}

答案 4 :(得分:0)

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

  }

这样,对内部类内输入的引用就没有问题。

答案 5 :(得分:0)

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

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

答案 6 :(得分:0)

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

答案 7 :(得分:0)

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