доступ к переменной внутри класса в Java - PullRequest
17 голосов
/ 10 октября 2010

Я пытаюсь создать массив 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] во внутреннем методе, но я не смог понять это.

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

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

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

Ответы [ 5 ]

27 голосов
/ 10 октября 2010

Ваша локальная переменная должна быть 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) перед телом внутреннего класса.


Ресурсы:

4 голосов
/ 10 октября 2010

Если у вас возникли проблемы с доступом к 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]);
}
2 голосов
/ 10 марта 2014

вы также можете использовать 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();
      }
   });
}
0 голосов
/ 10 октября 2010

Анонимные внутренние классы могут обращаться только к переменным включающего метода, которые final.

0 голосов
/ 10 октября 2010

Это происходит потому, что label не указано как final.

Объявите массив меток как:

final JLabel[] label;

вместо:

JLabel[] label;

Ваш MouseAdapter не является внутренним классом; это анонимный класс. Анонимные классы могут ссылаться только на final переменные своего кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...