这是多么低效:
List<Object> getList(){
return new LinkedList<Object>();
}
void foo(){
for(Object o: getList()){
do something with o;
}
}
Run Code Online (Sandbox Code Playgroud)
与此相比:
List<Object> getList(){
return new LinkedList<Object>();
}
void foo(){
List<Object> os = getList();
for(Object o: os){
do something with o;
}
}
Run Code Online (Sandbox Code Playgroud)
在
for(Object o: getList()) {
Run Code Online (Sandbox Code Playgroud)
getList()是一个表达式,它被计算一次,并iterator保留其结果(列表的引用).如果你担心这个代码会getList()在每次迭代时调用,那么它就不是真的(如果是,如果每次迭代以新列表开始时,列表至少有一个元素,那么它将是一个无限循环,在0元素处).
不会有任何可察觉的差异.
我编译了以下代码:
import java.util.LinkedList;
import java.util.List;
public class Test1 {
static List<Object> getList(){
return new LinkedList<Object>();
}
void process(Object o) {}
void foo1(){
for(Object o: getList()){
process(o);
}
}
void foo2(){
List<Object> os = getList();
for(Object o: os){
process(o);
}
}
}
Run Code Online (Sandbox Code Playgroud)
字节码为foo1和foo2如下:
void foo1();
Code:
0: invokestatic #26; //Method getList:()Ljava/util/List;
3: invokeinterface #28, 1; //InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
8: astore_2
9: goto 24
12: aload_2
13: invokeinterface #34, 1; //InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
18: astore_1
19: aload_0
20: aload_1
21: invokevirtual #40; //Method process:(Ljava/lang/Object;)V
24: aload_2
25: invokeinterface #42, 1; //InterfaceMethod java/util/Iterator.hasNext:()Z
30: ifne 12
33: return
void foo2();
Code:
0: invokestatic #26; //Method getList:()Ljava/util/List;
3: astore_1
4: aload_1
5: invokeinterface #28, 1; //InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
10: astore_3
11: goto 26
14: aload_3
15: invokeinterface #34, 1; //InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
20: astore_2
21: aload_0
22: aload_2
23: invokevirtual #40; //Method process:(Ljava/lang/Object;)V
26: aload_3
27: invokeinterface #42, 1; //InterfaceMethod java/util/Iterator.hasNext:()Z
32: ifne 14
35: return
Run Code Online (Sandbox Code Playgroud)
正如您自己看到的,两个循环的字节码是相同的.唯一的区别是foo2存储并在开始时将列表引用加载到局部变量中.
有人可能会争辩说,更好的优化编译器可以os完全消除,为两个函数生成相同的代码.
| 归档时间: |
|
| 查看次数: |
119 次 |
| 最近记录: |