Chinaunix首页 | 论坛 | 博客
  • 博客访问: 174748
  • 博文数量: 46
  • 博客积分: 1445
  • 博客等级: 上尉
  • 技术积分: 448
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-27 22:20
文章分类

全部博文(46)

文章存档

2013年(4)

2012年(12)

2011年(3)

2010年(5)

2009年(16)

2008年(6)

我的朋友

分类: Java

2009-12-29 14:07:41

//代码1

public class Obj {
    private int i;
    public int getI() {
        return i;
    }
    public void setI(int i) {
        this.i = i;
    }
}
//代码2

List result2 = new ArrayList();
Obj o =null;
for(int i=0;i<10;i++){
    o =new Obj();
    o.setI(i);
    result2.add(o);
}
//代码3

List result3 = new ArrayList();
for(int i=0;i<10;i++){
    Obj o =new Obj();
    o.setI(i);
    result3.add(o);
}



很多人的结论如下;

1)代码2比代码3的效率高;

2)代码2的可维护性不如代码3,因为变量作用域扩大了。

其实结论1)是错误的。

第2段代码反汇编及说明:
-----------------------------------------------------------------------
0:   new     #3;           //new ArrayList()
3:   dup                   //将新创建的ArrayList的引用复制并压入栈
4:   invokespecial   #4;   //编译器插入的ArrayList初始化方法:ArrayList.""
7:   astore_1              //局部变量赋值:result2 = new ArrayList();
8:   aconst_null           //局部变量赋值:o = null
9:   astore_2         

10:  iconst_0              //局部变量赋值:i = 0
11:  istore_3         
12:  iload_3               //比较i和10
13:  bipush  10
15:  if_icmpge       45    //如果i >= 10 函数返回
18:  new     #5;           //new Obj()
21:  dup                   //将新创建的Obj的引用复制并压入栈
22:  invokespecial   #6;   //编译器插入的Obj初始化方法 Method ""
25:  astore_2              //局部变量赋值:o = new Obj();
26:  aload_2               //准备调用参数栈,取出局部变量的引用并压栈: o
27:  iload_3               //准备调用参数栈,取出局部变量的值并压栈:i
28:  invokevirtual   #7;   //方法调用:o.set(i);
31:  aload_1               //取出局部变量的引用并压栈: result2
32:  aload_2               //取出局部变量的引用并压栈: o
33:  invokeinterface #8,  2;   //调用List.add()方法: result2.add(o);
38:  pop                  
39:  iinc    3, 1          //i++
42:  goto    12            //回到for循环头
45:  return                //函数返回
-----------------------------------------------------------------------

第3段代码反汇编及说明:
-----------------------------------------------------------------------
0:   new     #3;           //new ArrayList()
3:   dup                   /将新创建的ArrayList的引用复制并压入栈
4:   invokespecial   #4;   //编译器插入的ArrayList初始化方法:ArrayList.""
7:   astore_1              /局部变量赋值:result3 = new ArrayList();
8:   iconst_0              //局部变量赋值:i = 0                          
9:   istore_2                                                            
10:  iload_2               //比较i和10                                    
11:  bipush  10                                                           
13:  if_icmpge       43    //如果i >= 10 函数返回                        
16:  new     #5;           //new Obj()                                    
19:  dup                   //将新创建的Obj的引用复制并压入栈              
20:  invokespecial   #6;   //编译器插入的Obj初始化方法 Method ""
23:  astore_3              //局部变量赋值:o = new Obj();                 
24:  aload_3               //准备调用参数栈,取出局部变量的引用并压栈: o                 
25:  iload_2               //准备调用参数栈,取出局部变量的值并压栈:i                  
26:  invokevirtual   #7;   //方法调用:o.set(i);                          
29:  aload_1               //取出局部变量的引用并压栈: result3            
30:  aload_3               //取出局部变量的引用并压栈: o                  
31:  invokeinterface #8,  2;   //调用List.add()方法: result3.add(o);      
36:  pop                                                                  
37:  iinc    2, 1          //i++                                          
40:  goto    10            //回到for循环头                                
43:  return                //函数返回                                    
-----------------------------------------------------------------------

小结:
1、代码2效率显然不如代码3,红色那两行是多余的。
2、代码2可维护性比较差,冯勇强前面有说明。

代码2与代码3的差异,除了多了那两句,就是局部变量的索引顺序不同,循环体的反汇编也是完全一样的。所以,代码2各方面都不如代码3,一般推荐3的写法。这与大多数人日常编码习惯是一致的:)


阅读(421) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~