локальная переменная доступна во внутреннем классе (Java) - PullRequest
18 голосов
/ 13 апреля 2011

После получения кода я получил две ошибки.

Ошибки:

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 ]

16 голосов
/ 13 апреля 2011

Вам необходимо объявить

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

и

JComboBox c_age = new JComboBox(age);

следующим образом:

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

final JComboBox c_age = new JComboBox(age);

Это означает, что input и c_age не могут измениться:

Любая локальная переменная, используемая, но не объявленная во внутреннем классе, должна быть обязательно назначена перед телом внутреннего класса.

Объяснение взято из Спецификации языка Java, Раздел - 8.1.3 Внутренние классы и вложенные экземпляры

5 голосов
/ 13 апреля 2011

Если вы объявите переменные как окончательные, это решит ваши ошибки, но, по моему мнению, это не лучшее решение проблемы. Подобная проблема обсуждалась здесь, вы можете посмотреть здесь для большего понимания.

В решении вашей проблемы вы можете определить методы, используя их, вы можете получить лучшее решение. Для подсказки вы можете прочитать Как получить доступ к неконечной локальной переменной внутри анонимного внутреннего класса

2 голосов
/ 13 апреля 2011

Любая переменная, которую вы используете внутри метода 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);
        }

    }
1 голос
/ 28 сентября 2013

Поскольку добавление 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;
    }
}
0 голосов
/ 05 ноября 2012

Я только что создал временную переменную в главном классе, например, '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();
    }
}
0 голосов
/ 13 апреля 2011

Входная переменная и переменная c_age исчезают после завершения выполнения метода.Вам не разрешат использовать эти переменные внутри локальных внутренних классов, если они не являются окончательными.

0 голосов
/ 13 апреля 2011

Вы должны объявить final две переменные, к которым вы обращаетесь: input и c_age.

Если вы не хотите этого делать, то вы можете либо создать новый правильный класс (не специальный) и передать их в качестве параметров в конструкторе, либо (я сделал это при работе с GUI в Java ) создайте класс слушателя, который принимает объекты в своем конструкторе и делает их доступными локально, а затем создает их на заказ.

0 голосов
/ 13 апреля 2011

Именованный ввод JTextField был объявлен внутри основного метода. Вы, вероятно, должны сделать что-то вроде этого:

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

  }

Таким образом, ссылка на вход внутри внутреннего класса не доставит проблем.

...