开启一个新的问题(关于声明变量的性能问题) (问题结束)

在我们编程的过程中经常会遇到这样的问题。
ExpandedBlockStart.gif ContractedBlock.gif for  ( int  i = 0 ;i < n;i ++ ) dot.gif {
InBlock.gif    String str 
= //dot.gif
ExpandedBlockEnd.gif
}

None.gifString str 
=   null ;
ExpandedBlockStart.gifContractedBlock.gif
for ( int  i = 0 ;i < n;i ++ ) dot.gif {
InBlock.gif    str 
= //dot.gif
ExpandedBlockEnd.gif
}

None.gif
None.gif

在印象中一直认为方法二的性能好于方法一,但是差距应该很小。但因为一位别人的回文说方法一极大的影响了性能,所以想写个例子证明一下相差很小。例子如下:
ExpandedBlockStart.gif ContractedBlock.gif public   class  TestOt  dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public static void main(String[] args) dot.gif{
InBlock.gif        
long n=1000000000;
InBlock.gif        
long start = System.currentTimeMillis();
InBlock.gif        test2(n);
InBlock.gif        
long end = System.currentTimeMillis();
InBlock.gif        System.out.println(end
-start);
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
public static void test1(long n)dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
for (int i=0;i<n;i++)dot.gif{
InBlock.gif            String str 
= "";
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
public static void test2(long n)dot.gif{
InBlock.gif        String str 
= null;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
for (int i=0;i<n;i++)dot.gif{
InBlock.gif            str 
= "";
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}
测试的结果是当n=10亿次的时候差距是1秒,所以说差距应该是很小的,符合我原始的记忆,但是另一个问题来了,测试的结果是
方法一:3300毫秒左右
方法二:4300毫秒左右
结果刚好相反,于是更改方法
None.gif
ExpandedBlockStart.gifContractedBlock.gif
public   class  TestOt  dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif    
public static void main(String[] args) dot.gif{
InBlock.gif        
long n=1000000000;
InBlock.gif        
long start = System.currentTimeMillis();
InBlock.gif        test1(n);
InBlock.gif        
long end = System.currentTimeMillis();
InBlock.gif        System.out.println(end
-start);
ExpandedSubBlockEnd.gif    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
public static void test1(long n)dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
for (int i=0;i<n;i++)dot.gif{
InBlock.gif            String str 
= null;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedSubBlockStart.gifContractedSubBlock.gif    
public static void test2(long n)dot.gif{
InBlock.gif        String str 
= null;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
for (int i=0;i<n;i++)dot.gif{
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif
结果依旧。

没办法,取得字节码,对比
ExpandedBlockStart.gif ContractedBlock.gif public   class  TestOt  extends  java.lang.Object dot.gif {
InBlock.gif
public TestOt();
InBlock.gif  Code:
InBlock.gif   
0:   aload_0
InBlock.gif   
1:   invokespecial   #8//Method java/lang/Object."<init>":()V
InBlock.gif
   4:   return
InBlock.gif
InBlock.gif
public static void test1(int);
InBlock.gif  Code:
InBlock.gif   
0:   iconst_0
InBlock.gif   
1:   istore_1
InBlock.gif   
2:   goto    10   
InBlock.gif   
5:   aconst_null
InBlock.gif   
6:   astore_2
InBlock.gif   
7:   iinc    11
InBlock.gif   
10:  iload_1   
InBlock.gif   
11:  iload_0
InBlock.gif   
12:  if_icmplt       5
InBlock.gif   
15:  return
InBlock.gif
InBlock.gif
public static void test2(int);
InBlock.gif  Code:
InBlock.gif   
0:   aconst_null
InBlock.gif   
1:   astore_1
InBlock.gif   
2:   iconst_0
InBlock.gif   
3:   istore_2
InBlock.gif   
4:   goto    10   
InBlock.gif   
7:   iinc    21
InBlock.gif   
10:  iload_2   
InBlock.gif   
11:  iload_0  
InBlock.gif   
12:  if_icmplt       7
InBlock.gif   
15:  return
ExpandedBlockEnd.gif}

结果是感觉还是应该是方法二快,那为什么反而方法一快了1秒左右呢?
不得而知,现在我个人猜测的想法是可能有两种情况:
1,JLS的底层定义决定的,有什么特殊的优化?
2,因为方法二比方法一虽然少了在循环中的部分,但是引用的声明周期反而是更长了,是否因为引用存在造成了方法二的栈操作消耗了大部分时间?
猜想一有待于JLS文档的查阅,我会在有空的时候查询,猜想二正在想办法证明。
看文章的朋友,如果谁了解麻烦指点一下,是我的测试方法写的有问题,还是别的原因,谢谢。

最后:问题已经基本了解了原因,见回复中的讨论,谢谢--daydream 的帮忙。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值