【问题标题】:local variable is accessed within inner class (java)在内部类(java)中访问局部变量
【发布时间】:2011-08-04 09:35:11
【问题描述】:

编译代码后出现两个错误。

错误是:

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

}

我该如何解决这个错误?

【问题讨论】:

    标签: java actionlistener inner-classes final


    【解决方案1】:

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

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

    【讨论】:

    • 以其他方式,您可以将 input 和 c_age 变量声明为静态实例变量,从而解决您的问题。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      你需要声明

      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

      【讨论】:

      • 问题已解决。但我不明白你的解释。希望你能提供更多......非常感谢爱德华
      • 附上 Java 语言规范的摘录和链接,希望对您有所帮助...
      • final 是必需的,以便用户在内部类/闭包使用时无法更改变量。想一想:如果它没有被标记为 final,内部类引用可以完成声明旁边的一些代码可以做的所有事情,因此您必须将其标记为 final 以避免并发问题,并且语法强制执行此操作。
      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

          您在内部类的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吗?
          【解决方案7】:

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

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

          【讨论】:

            【解决方案8】:

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

            这样在内部类中对输入的引用就不会出现问题。

            【讨论】:

            • 我有这个错误:不能从静态上下文中引用非静态变量
            • 主要方法是静态上下文。你必须通过实例化你的类的一个实例来打破它,就像我的例子一样。然后你的 main 方法中的各种代码应该进入构造函数。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-06-29
            • 1970-01-01
            相关资源
            最近更新 更多