Доступ к переменной внутри внутреннего класса в java
Я пытаюсь создать массив JLabels, все они должны быть невидимыми при нажатии. Проблема возникает при попытке настроить прослушиватель мыши через внутренний класс, которому нужен доступ к переменной итерации цикла, используемого для объявления меток. Код не требует пояснений:
for(int i=1; i<label.length; i++) {
label[i] = new JLabel("label " + i);
label[i].addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
label[i].setVisible(false); // compilation error here
}
});
cpane.add(label[i]);
}
Я думал, что могу преодолеть это с помощью this
или, может быть, super
вместо вызова label[i]
внутри внутреннего метода, но я не смог его понять.
Ошибка компиляции: локальная переменная я доступна изнутри внутреннего класса; должен быть объявлен окончательным `
Я уверен, что ответ должен быть чем-то действительно глупым, о котором я не думал, или, может быть, я делаю небольшую ошибку.
Любая помощь будет оценена
Ответы
Ответ 1
Локальная переменная должна быть final
для доступа из внутреннего (и анонимного) класса.
Вы можете изменить свой код на что-то вроде этого:
for (int i = 1; i < label.length; i++) {
final JLabel currentLabel =new JLabel("label " + i);
currentLabel.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
currentLabel.setVisible(false); // No more compilation error here
}
});
label[i] = currentLabel;
}
Из JLS:
Любая локальная переменная, формальный параметр или параметр исключения, используемые, но не объявленные во внутреннем классе, должны быть объявлены final
.
Любая локальная переменная, используемая, но не объявленная во внутреннем классе, должна быть обязательно назначена (§16) перед телом внутреннего класса.
Ресурсы:
Ответ 2
Если у вас возникла проблема с доступом к i
, сделайте другую переменную вне области вашего внутреннего класса (например, до label[i].addMouseListener(...)
):
for(int i=1; i<label.length; i++) {
label[i] = new JLabel("label " + i);
final int localI = i;
label[i].addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
label[localI].setVisible(false);
}
});
cpane.add(label[i]);
}
Ответ 3
вы также можете использовать getSource
в своей программе. После этого вы можете получить доступ к своему компоненту с помощью typecasting
. это уменьшит дополнительные строки кода,
ваш код будет выглядеть следующим образом:
for (int i = 1; i < label.length; i++) {
currentLabel.addMouseListener(new MouseAdapter(e) {
public void mouseClicked(MouseEvent me) {
JLabel label = (JLabel) me.getSource();
}
});
}
Ответ 4
Это происходит потому, что label
не указывается как final
.
Объявите массив меток как:
final JLabel[] label;
вместо:
JLabel[] label;
Ваш MouseAdapter
не является внутренним классом; это анонимный класс. Анонимные классы могут ссылаться только на переменные final
их прилагаемого кода.
Ответ 5
Анонимные внутренние классы могут обращаться только к переменным вложенного метода final
.