我有这个for-each-loop:
for (Component c : container.getComponents()) {
// Loop code
}
每次迭代都会调用getComponents
吗?在外观之前调用getComponents
并且仅在缓存的数组上工作是否有意义?
答案 0 :(得分:17)
不,getComponents()只会被调用一次。
相当于:
for (Iterator<Component> iterator = container.getComponents().getIterator();
iterator.hasNext(); )
{
Component c = iterator.next();
...
}
来自section 14.14.2 of the Java Language Specification:
增强的for语句具有以下形式:
EnhancedForStatement:
for ( VariableModifiersopt Type Identifier: Expression) Statement
Expression必须具有Iterable类型,否则它必须是数组类型(第10.1节),&gt;或发生编译时错误。 在FormalParameter部分中声明的局部变量的范围是增强的 声明(第14.14节)是包含的声明
增强的for语句的含义是通过翻译成基本的
for
来给出的 言。如果Expression的类型是
Iterable
的子类型,那么让我成为它的类型 表达Expression.iterator()
。增强的for语句相当于一个基本的for
表格声明:for (I #i = Expression.iterator(); #i.hasNext(); ) { VariableModifiersopt Type Identifier = #i.next(); Statement }
答案 1 :(得分:10)
getComponents将被调用一次,并将返回一个Iterator。然后使用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();
另外,由于我们从JLS 14.14.1知道for语句的第一部分只执行一次,我们可以放心,迭代器方法不会被多次调用。
答案 2 :(得分:3)
Java LanguageSpecification 14.14.2说:
EnhancedForStatement:
for ( VariableModifiersopt Type Identifier: Expression) Statement
如果Expression的类型是Iterable的子类型,那么让我成为表达式Expression.iterator()的类型。增强的for语句相当于表单的基本语句:
for (I #i = Expression.iterator(); #i.hasNext(); ) {
VariableModifiersopt Type Identifier = #i.next();
Statement
}
其中#i是编译器生成的 与任何不同的标识符 其他标识符(编译器生成的 或者在其他方面)在范围内(§6.3) 在增强的点 声明发生。
因此表达式仅被评估一次(在初始化期间)。
答案 3 :(得分:2)
每个人都会调用getComponents吗? 迭代?
没有。 Java的foreach循环基于Iterable接口,相当于此代码
Iterator<Component> i = container.getComponents().iterator
while(i.hasNext()) {
Component c = i.next();
// loop body goes here
}
唯一的区别是Iterator是隐藏的。
答案 4 :(得分:0)
我原本以为在编译时,它会被转换为循环的“长手”,就像使用for(int i = 0 ....
一样foreach循环不仅仅是编程节省时间,实际的字节码转换与“长手”一样吗?
简而言之,只应调用getComponent()一次