foreach с именем переменной, равным имени поля - PullRequest
21 голосов
/ 29 января 2012

Нашел интересную вещь при компиляции следующего фрагмента кода:

1    class A {
2        
3     private B line;
4   
5     public void foo() {
6       for (Integer line : line.getElements()) {
7    
8       }
9     }
10    }
11    
12    class B {
13    
14      List<Integer> getElements() {
15         return null; // doesn't matter
16      }
17    }

Обратите внимание на строку 6: мы видим, что имя переменной равно имени поляIntelliJ Idea 11 игнорирует это и думает, что здесь нет проблем.Но компилятор Java говорит мне, что «строка не имеет метода getElements».Итак, два вопроса:

  1. Должен ли я отправить отчет об ошибке в Idea?
  2. Почему сообщение об ошибке от Java такоеРазве это не в состоянии обнаружить ошибку?Какой механизм работает здесь?Затмение переменной поля?

Ответы [ 3 ]

13 голосов
/ 29 января 2012

Это может быть ошибка в используемом вами компиляторе Java.В соответствии с спецификацией языка Java (раздел 14.14.2) область действия переменной в расширенном операторе for является оператором содержимого.(Кажется, это исключает итеративное или массивное выражение справа от :.)

Вы можете обойти эту проблему, используя this.line.getElements().

EDIT Просто для удовольствия, я отправил это сообщение об ошибке в Sun.Посмотрим, считают ли инженеры Java ошибку в JLS или в javac (или у них есть какое-то другое объяснение).Идентификатор ошибки: 7139681 , хотя он не будет опубликован во внешней базе данных в течение нескольких дней.

7 голосов
/ 29 января 2012

Если вы объявите локальную переменную (что вы и сделали) с тем же именем, что и поле, тогда вы сможете получить доступ к переменной поля как this.name.

for (Integer line : this.line.getElements()) {
}
0 голосов
/ 29 января 2012

Когда вы используете IntelliJ, он автоматически анализирует все файлы.Однако с javac он может не скомпилировать все программы, особенно если они были скомпилированы ранее.

Скажем, у вас есть класс B (без getElements ()), и вы скомпилируете его.Позже вы добавляете метод и компилируете только A, он будет жаловаться, что B не имеет этого метода, потому что в последний раз, когда вы его компилировали, такого метода не было.

Способ обойти это - удалить все* .class файлы перед компиляцией или использованием инструмента сборки, такого как maven.

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