Подтвердить что ты не робот

Доступ к переменной внутри внутреннего класса в 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] внутри внутреннего метода, но я не смог его понять.

Ошибка компиляции: локальная переменная я доступна изнутри внутреннего класса; должен быть объявлен окончательным `

Я уверен, что ответ должен быть чем-то действительно глупым, о котором я не думал, или, может быть, я делаю небольшую ошибку.

Любая помощь будет оценена

4b9b3361

Ответ 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.