下面两段代码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,
按理说比第一段要慢,就算是编译的时候已经优化过了,
也不应该比第一段快才是?

解决方案 »

  1.   

    我觉得照成此问题的并不是装箱与解箱的问题.
    而是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);
    }
    }
      

  2.   

    第二段应该不会快啊,你这个循环有可能直接被编译器优化掉了 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);
    }
      

  3.   

    个人感觉:1.Integer b = 1;是有个装箱的步骤。2.基本数据类型在于String相加的时候应该是会调用String.valueOf(i);而Integer会执行toString方法,方法的入栈出栈也存在的一定的差异。当然这些只是猜测。
    当循环增加到100000000次后与10000次的平均循环时间比其实有降低。
      

  4.   

    谢谢楼上各位的回答~刚才试了下,
    把两个.class文件分别用javap查看
    关键的区别应该在第一段的+操作是(Integer)
       33: invokevirtual #40; //Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
    第二段的是(int)
       30: invokevirtual #35; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
    看了下源代码,append(Object)是需要把字符串的内容arraycopy一次,
    append(int)只是把自己内部的char[]传到Integer的一个static方法里面,简单的拼在后面
    也许是这个原因?
      

  5.   


    这个是把数字加大后visualvm的图,划掉的是System.in.read(),无视掉..
    看起来主要区别就是append这个方法差很多..
      

  6.   

    再算一下,上面的图是100000000次循环下的
    Integer用的时间是20013-划掉的3195=16818
    int用的时间14188-划掉的2294=11894
    差值是4924
    Integer的append-int的append=6255 - 1894=4361
    88%的时间差都是这个方法造成的..
    看来大概是这么个问题吧..
      

  7.   

    应该就是这个原因,int转为String代价更小一些
      

  8.   


    应该是Integer转String的代价要小些吧
    Integer的toString()方法做了相关优化    Integer b = 1;
        long begin = System.nanoTime();
        System.out.println(b);
        System.out.println(System.nanoTime() - begin);    int b = 1;
        
        long begin = System.nanoTime();
        System.out.println(""+b);
        System.out.println(System.nanoTime() - begin);  时间也是前一段代码执行的时间短一些啊
      

  9.   

    口说无凭,佐证
    http://blog.sina.com.cn/s/blog_4b50130d0100u3vh.html优化的:
    http://pnuts.cc/2010/01/int-to-string/comment-page-1/?replytocom=753
      

  10.   

    你确定?public static void main(String[] args) {
    Integer b = 1;
        long begin = System.nanoTime();
        System.out.println("" + b);
        System.out.println(System.nanoTime() - begin);
        
        int c = 1;
        begin = System.nanoTime();
        System.out.println(""+c);
        System.out.println(System.nanoTime() - begin);
    }这个代码执行结果是
    1
    202202
    1
    41332
      

  11.   

    我的结论就是你后面这个帖子说的啊,
    append(int)比append(Object)的效率高,
    所以int b = 1的要比Integer b = 1的那段要快