2009-10-09 2 views

ответ

17

Нет, getComponents() будет вызываться только один раз.

Это эквивалент:

for (Iterator<Component> iterator = container.getComponents().getIterator(); 
    iterator.hasNext();) 
{ 
    Component c = iterator.next(); 
    ... 
} 

От section 14.14.2 of the Java Language Specification:

Усиленный для постановки имеет вид:

EnhancedForStatement:

for (VariableModifiersopt Type Identifier: Expression) Statement 

Выражение должно иметь тип Iterable, иначе он должен быть типа массива (§10.1),> или возникает ошибка времени компиляции. Область действия локальной переменной, объявленной в FormalParameter части расширенной для заявления (§14.14) является содержащаяся Заявление

Значение расширенной для постановки дается перевод в основной for заявления.

Если тип выражения является подтипом Iterable, тогда позвольте мне быть типом выражения Expression.iterator(). Усовершенствовано для утверждения эквивалентно основного for утверждения формы:

for (I #i = Expression.iterator(); #i.hasNext();) { 
    VariableModifiersopt Type Identifier = #i.next(); 
    Statement 
} 
+1

Jon, как компилятор гарантирует, что getComponents() не имеет побочных эффектов и не производит что-то другое на каждой итерации? (например, если другой поток изменяет компонент?). – Uri

+1

Это не ... но перевод выше - это в основном то, что он определяет. Я попытаюсь найти ссылку на JLS. –

+0

Мой плохой. Я неправильно читаю исходный код. Я думал, что ОП спрашивает, переоценивается ли условие управления в цикле for. Я не заметил, что это было для каждого. – Uri

0

я бы подумал, что при компиляции, он будет переведен, чтобы быть «длинная рука» для петли, как в использовании для (INT I = 0 ....

Не цикл Еогеасп просто время программирования заставка с фактической байт-кода перевода так же, как это делать «длинные руки» ??

Короче говоря, GetComponent() должна вызываться только один раз

+1

Нет, это не так, как работает цикл foreach (хотя верно, что getComponent() будет вызываться только один раз). –

+0

Это не заслуживало -1 (фактический ответ, который вы дали, правильный, хотя предположение до него неверно), так что вот +1. –

10

getComponents будет вызываться один раз, и возвращает итератор Этот итератор будет вызываться с использованием методов next() и hasNext().

Обновление Подробнее о попытке выхода Skeet Jon Skeet на этот ответ.

Следующая программа показывает, как вызов iterator выполняется один раз, хотя в коллекции есть три элемента.

public static void main(String[] args) { 
    List<String> list = new ArrayList<String>() { 
     public java.util.Iterator<String> iterator() { 
      System.out.println("iterator() called"); 
      return super.iterator(); 
     }; 
    }; 
    list.add("a"); 
    list.add("b"); 
    list.add("c"); 

    for (String s : list) { 
     System.out.println(s); 
    } 
} 

Выход:

iterator() called 
a 
b 
c 

Если запустить это через декомпилятор Java, вы увидите следующий код:

String s; 
    for(Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println(s)) 
     s = (String)iterator.next(); 

Addtionally, так как мы знаем из JLS 14.14.1, что первый раздел инструкции for выполняется только один раз, мы можем быть уверены, что метод iterator не будет вызываться несколько раз.

2

Называется getComponents на каждой итерации ?

цикл Еогеасп-номер Java базируется на интерфейсе Iterable, и эквивалентен этому коду

Единственное отличие состоит в том, что итератор скрыта.

3

Java LanguageSpecification 14.14.2 говорит:

EnhancedForStatement:
for (VariableModifiersopt Type Identifier: Expression) Statement

Если тип выражения является подтипом Iterable, то пусть я буду тип выражения Expression.iterator() , Усиливается для постановки эквивалентно основной для постановки формы:

for (I #i = Expression.iterator(); #i.hasNext();) { 

     VariableModifiersopt Type Identifier = #i.next(); 
    Statement 
} 

Где #i является сгенерированный компилятором идентификатор, который отличен от любых других идентификаторов (сгенерированный компилятором или в противном случае), которые находятся в области (§6.3) в том месте, где выполняется расширение для выражения .

Таким образом, выражение оценивается только один раз (во время инициализации).