日期:2014-05-20  浏览次数:20706 次

请教一个装箱拆箱的问题
下面两段代码

String a = "abc";
Integer b = 1;
String c = null;
long begin = System.nanoTime();
for(int i = 0; i < 1000; i ++){
c = a + b;
}
System.out.println(System.nanoTime() - begin);



String a = "abc";
int b = 1;
String c = null;
long begin = System.nanoTime();
for(int i = 0; i < 1000; i ++){
c = a + b;
}
System.out.println(System.nanoTime() - begin);

第二段要比第一段快30%的样子,为什么?
我理解的是a+b的时候要把b自动装箱成Integer,然后toString,
按理说比第一段要慢,就算是编译的时候已经优化过了,
也不应该比第一段快才是?

------解决方案--------------------
我觉得照成此问题的并不是装箱与解箱的问题.
而是String类中“+”的问题。
前一种方法c=a+b;相当于c=a+b.toString();
  照成了for循环中一直在new String类型的对象
而后一种方法则涉及到了String类中的“+”运算符的问题:
   Java只是不支持自定义运算符重载,这个String类的+就是运算符重载,
   也是Java中仅有的一个运算符重载,它是通过编译器实现的,
   在语法解析阶段就已经确定了
  具体来说后一种方法
    c=a+b;相当于c= new StringBuilder().append(a).append(b).toString();



如果仅仅比较Integer().toString与1+“”的效率的话
前者的效率应该高些。
原因在于Integer().toString方法在java中实现了很多的优化
public class Test1 {
public static void main(String[] args) {

    Integer b = 1;
   
    long begin = System.nanoTime();
    System.out.println(b);
    System.out.println(System.nanoTime() - begin);
}
}

public class Test2 {
public static void main(String[] args) {

    int b = 1;
   
    long begin = System.nanoTime();
   System.out.println(""+b);
    System.out.println(System.nanoTime() - begin);
}
}


------解决方案--------------------
顶,坐等高手
------解决方案--------------------
第二段应该不会快啊,你这个循环有可能直接被编译器优化掉了
	volatile int i  ;
public void haha(){
String a = "abc";
Integer b = 1;
String c = null;
long begin = System.nanoTime();
for( i = 0 ; i < 1000; i ++){
c = a + b;
}
System.out.println(System.nanoTime() - begin);
System.out.println(c);
}

------解决方案--------------------
你的第二段代码, b是个基本数据类型。当在与字符串进行拼接的时候是直接来的,不需要在转化,也就是你说的拆箱。

而你的第一段代码,b是个引用数据类型,每次执行拼接的时候都要,进行拆箱,你说那个慢?
 
就好像每一次循环第一次比第二次 多做了点事,所以就慢的罗
------解决方案--------------------
个人感觉:1.Integer b = 1;是有个装箱的步骤。2.基本数据类型在于String相加的时候应该是会调用String.valueOf(i);而Integer会执行toString方法,方法的入栈出栈也存在的一定的差异。当然这些只是猜测。