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

Foreach с именем переменной, равным имени поля

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

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". Итак, два вопроса:

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

Ответ 1

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

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

ИЗМЕНИТЬ Просто для ударов, я представил это как отчет об ошибке для Sun. Мы увидим, считают ли инженеры Java ошибкой в ​​JLS или в javac (или если у них есть другое объяснение). Идентификатор ошибки 7139681, хотя он не будет отправлен во внешнюю базу данных в течение нескольких дней.

Ответ 2

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

for (Integer line : this.line.getElements()) {
}

Ответ 3

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

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

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