Доступ к локальной переменной осуществляется внутри внутреннего класса (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 Name");
JTextField input = new JTextField("",10);
JLabel l2 = new JLabel("Choose Your Child 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);
}
}
Как я могу решить эту ошибку?
Ответы
Ответ 1
Вам нужно объявить
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 Внутренние классы и экземпляры Enclosing
Ответ 2
Если вы объявите переменные в качестве окончательного, то он решит ваши ошибки, но, по моему мнению, это не хорошее решение проблемы. Подобная проблема обсуждалась здесь, вы можете посмотреть здесь для лучшего понимания.
В решении вашей проблемы вы можете определить методы, используя их, вы можете получить лучшее решение. Для подсказки вы можете прочитать Как получить доступ к не конечной локальной переменной внутри анонимного внутреннего класса
Ответ 3
Любая переменная, которую вы используете внутри метода actionPerformed
вашего внутреннего класса, должна быть объявлена окончательной. Попробуйте следующее:
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 Name");
final JTextField input = new JTextField("",10);
JLabel l2 = new JLabel("Choose Your Child 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);
}
}
Ответ 4
Как добавление final
устраняет большую гибкость, я хотел бы предложить следующее: создать метод доступа, который в любом случае поощряется. Но это в основном полезно при работе с объектами, тогда как в вашем случае все статично. Таким образом, этот ответ может не применяться к вашей конкретной ситуации, но поскольку поиск в Google для вашего сообщения об ошибке дает этот вопрос в качестве верхнего результата, я думаю, что альтернатива, применимая в большинстве случаев (использование объектов более распространено, чем выполнение всего от статического метода) также должны присутствовать здесь.
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;
}
}
Ответ 5
Именованный вход 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.
}
}
Таким образом, ссылка на ввод внутри внутреннего класса не даст никаких проблем.
Ответ 6
Вы должны объявить final
две переменные, которые вы используете: input
и c_age
.
Если вы не хотите этого делать, вы можете либо создать новый правильный класс (а не рекламный), либо передать его в качестве параметров в конструкторе, либо (я сделал это при работе с GUI в Java ) создайте класс слушателя, который принимает объекты в своем конструкторе и делает их доступными локально, затем ad-hoc создает экземпляр этого файла.
Ответ 7
Входная переменная и переменная c_age исчезают после завершения выполнения метода. Вам не разрешат использовать эти переменные внутри локальных внутренних классов, если они не являются окончательными.
Ответ 8
Я только что создал временный 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 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();
}
}