今天看"Java Performance Tuning",书中提到下面的过程无论何时被调用都会产生两个临时字符串对象然后就被丢弃了。public String sayHi(String title, String name)
{
  return "hi " + title + " " + name;
}我猜测这里面产生的两个对象应该是"hi "和" ",但是我理解这两个对象应该是从String pool产生的吧,如果String pool没有这两个对象,会新生成,如果已经存在那么应该直接返回这两个对象。所以应该不会存在书中提到的现象。不知道我的理解是否正确,请各位指正。

解决方案 »

  1.   

    "hi   "和"   "产生之后没有对他们的引用,所以return之后就没有了吧,我是这样理解的
      

  2.   

    貌似"hi"和" "存在于池中(没有就先在池子里创建),然后再复制一份以供sayHi方法使用...
    最后被丢弃的应该是复制的那两个String对象...
      

  3.   

    貌似"hi"和"   "存在于池中(没有就先在池子里创建),然后再复制一份以供sayHi方法使用... 
    最后被丢弃的应该是复制的那两个String对象...
    --------------------------------------------------------------------------嗯,有道理。不过,String对象具有恒常性的,不会被修改,操作String对象的方法都会返回一个新的Stirng对象,那么应该直接从池中取出对象,复制一份好像没什么意义吧。
      

  4.   

    由字节码,明显上面指的临时对象是指sayHi(*,*)的两个参数分别对应aload_1和aload_2,在方法体return   "hi   "   +   title   +   "   "   +   name;中,只产生了一个StringBuilder对象,而且这个对象是以toString返回的.public java.lang.String sayHi(java.lang.String, java.lang.String);
      Code:
       0:   new     #2; //class java/lang/StringBuilder
       3:   dup
       4:   invokespecial   #3; //Method java/lang/StringBuilder."<init>":()V
       7:   ldc     #4; //String hi
       9:   invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava/lang/
    String;)Ljava/lang/StringBuilder;
       12:  aload_1
       13:  invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava/lang/
    String;)Ljava/lang/StringBuilder;
       16:  ldc     #6; //String
       18:  invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava/lang/
    String;)Ljava/lang/StringBuilder;
       21:  aload_2
       22:  invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava/lang/
    String;)Ljava/lang/StringBuilder;
       25:  invokevirtual   #7; //Method java/lang/StringBuilder.toString:()Ljava/la
    ng/String;
       28:  areturn
      

  5.   

    回6楼,记得貌似池子里的对象是不会使用的,复制一份用来进行对象的相关操作....
    所有操作都针对副本进行....操作结束副本就被回收了...也就是说String池子不是冰箱:冷冻-->取出来使用-->用完继续冷冻
    而更接近于画廊:展品-->照着展品画个复制品-->有新画-->把新画放进画廊...所以String效率不如StringBuffer高喵~~~~
      

  6.   

    以前的理解有问题,这两个额外产生的对象不是常量,而应该是那两个变量。字符串常量应该是直接从池中引用,不会产生新的对象。而对字符串变量的连接操作,刚才也提到过,会产生新的字符串对象。
    还有个问题就是如果改成"return (new StringBuffer(  )).append("hi ").append(title).append(" ").append(name).toString(  );",难道就不会产生这两个额外的对象吗?
      

  7.   

    回7楼:
    String池子的相关操作应该是JVM自己做的吧,这个在字节码里是看不出来的...
    只能看到关于String类的append操作过程:转化为StringBuilder或者StringBuffer来进行,最后toString一个新String作为结果.
    字节码的9,13,18,22行所用到的String(应该分别是"hi",title," ",name)都已经是副本了...
      

  8.   

    回9楼:
    这么说貌似怪怪的,String不是Java的那8种基础类型之一,常量/变量容易说糊涂,把它看作一个特殊点的类更好理解....9楼的例子不会有额外对象,其实String的相加本来也都是转化为StringBuffer之后进行的...更正我8楼的错误: "hi"这样的对象是直接引用String池的,new出的对象才是副本,谢谢lz在6楼指出....
      

  9.   

    别客气啊,11楼说得对。但是搞不清楚StringBuffer操作String对象为什么不会产生额外的对象。
      

  10.   

    StringBuffer操作的是StringBuffer类,它和String类完全不同,就是一个普通的类而已...StringBuffer类和String最大区别--它不是不可变类,也没有池子,它的append是真正意义上的追加,整个操作过程不需要借助新对象...
      

  11.   

    StringBuffer是可以的 它的append方法就是纯粹的追加的方法  
    他和string是不同的
    string 他是一个引用类型  当他连接字符串的时候 他所连的hi 和 "" 也同样占用内存创建他们  之后再连接起来 
      

  12.   

    以前总认为引用String对象就会产生新的副本,这样StringBuffer的Append方法也会产生副本,看来以前的想法有问题。String对象的加法操作会产生临时的对象,只是最后一个加法运算产生的临时对象会返回,在这之前的加法操作确实是“产生临时对象然后后又抛弃了”。而StringBuffer的Append只是引用String Pool中的String对象,不会产生新的String,可以降低开销。又有新的认识了,呵呵。多谢各位的参与。