是否会在每次迭代时评估此代码?

Dan*_*ski 4 java performance loops

我有这个for-each-loop:

for (Component c : container.getComponents()) {
    // Loop code
}
Run Code Online (Sandbox Code Playgroud)

getComponents每次迭代都会被调用吗?getComponents在外观之前调用并且仅在缓存数组上工作是否有意义?

Jon*_*eet 17

不,getComponents()只会被调用一次.

它相当于:

for (Iterator<Component> iterator = container.getComponents().getIterator();
     iterator.hasNext(); )
{
    Component c = iterator.next();
    ...
}
Run Code Online (Sandbox Code Playgroud)

Java语言规范的14.14.2节:

增强的for语句具有以下形式:

EnhancedForStatement:

for ( VariableModifiersopt Type Identifier: Expression) Statement
Run Code Online (Sandbox Code Playgroud)

Expression必须具有Iterable类型,否则它必须是数组类型(第10.1节),>或发生编译时错误.在增强的for语句(第14.14节)的FormalParameter部分中声明的局部变量的范围是包含的Statement

增强的for语句的含义是通过翻译成基本for 语句给出的.

如果Expression的类型是子类型Iterable,那么让我成为表达式的类型Expression.iterator().增强的for语句等同于for表单的基本 语句:

for (I #i = Expression.iterator(); #i.hasNext(); ) {
   VariableModifiersopt Type Identifier = #i.next();
   Statement
}
Run Code Online (Sandbox Code Playgroud)


bri*_*gge 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

iterator() called
a
b
c
Run Code Online (Sandbox Code Playgroud)

如果您通过Java反编译器运行它,您将找到以下代码:

    String s;
    for(Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println(s))
        s = (String)iterator.next();
Run Code Online (Sandbox Code Playgroud)

另外,由于我们从JLS 14.14.1中知道for语句的第一部分只执行一次,我们可以放心,迭代器方法不会被多次调用.