Назначение полей в объявлении Java foreach - PullRequest
3 голосов
/ 05 октября 2010

Я знаю, что цикл foreach, использованный в следующем примере, не компилируется.Но кто-нибудь знает, почему использование поля в объявлении цикла foreach не разрешено?

public class Foo {
    private Object obj;

    public void run(List<Object> objects) {
        for (obj : objects) {
            process();
        }
    }

    private void process() {
        // do something with obj
    }
}

Ответы [ 5 ]

7 голосов
/ 06 октября 2010

Возможно, потому что

  • ограничивает область действия переменной цикла (таким образом, делая код более понятным и избегая возможных незначительных ошибок), а
  • упрощает синтаксический анализ для компилятора.
2 голосов
/ 06 октября 2010

Обычно не имеет смысла присваивать поле в цикле foreach.Область действия объекта в цикле foreach - это всего лишь одна итерация цикла, тогда как область действия поля - это время существования объекта.* ... вы бы ничего не получили, сохранив ссылку в виде поля.Кроме того, если вы действительно этого хотите, вы можете просто назначить поле вручную, используя this.obj = obj.

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

Был еще отчет об ошибке по этому вопросу еще в 2004 году. Он был отклонен, и ответ интересен:

Существует определенный подход «прежде всего безопасности»заставить объявить переменную цикла внутри цикла (см. перевод в JLS 14.14.2).Во-первых, нет никакой опасности случайно заглушить переменную в области видимости.Во-вторых, использование новой переменной цикла в каждой итерации позволяет избежать проблем параллелизма, если переменная передается другим потокам телом цикла.В-третьих, компилятор может оптимизировать, объявив переменную цикла как 'final'.В-четвертых, если переменная во вложенной области была повторно использована в качестве переменной цикла, и у программиста возникла идея, что цикл обходит всю коллекцию, они могут ожидать, что смогут наблюдать последний элемент в коллекции после итерации через циклпеременная.Но это не обязательно относится к последнему элементу, например, если цикл сделал разрыв.

1 голос
/ 06 октября 2010

Какое значение должно иметь obj до запуска цикла for, и какое значение оно должно иметь после запуска цикла?Это будет сбивать с толку.

1 голос
/ 06 октября 2010

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

Одна вещь, которая может сбить с толку, - это «что будет значением obj после выполнения цикла»? В отличие от стандартного цикла for, расширенный цикл for-each не пытается гарантировать собственную механику.

Другое дело, что поля экземпляра представляют состояние объекта. При использовании поля экземпляра в цикле for-each можно сказать, что объект может перейти из одного состояния в одно или несколько промежуточных состояний, а затем в конечное состояние в течение одной операции . Это просто плохой дизайн, и его стоит предотвратить.

Почему бы не передать obj в качестве аргумента process()?

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