final String str1 = "length: 10";
final String str2 = "length: "+pig.length();我现在可以确定str1==str2为false;
我知道String池的特性
但想知道连接操作符“+”的定义,他是否是new了一个新的字符串?还是什么?
望达人指点!

解决方案 »

  1.   

    个人理解,:
    eg: "length1"+"length2"+  操作符 是把 new 一个新的字符串即length2
    然后把  length1和length2连接起来,放入一个新的空间里,str2指向他个人理解,有错改正,,哈哈学习!!!!!
      

  2.   

    其实我是这么想的
    就是“+”new了一个新的String对象,然后将操作数两个String常量拷贝到new 的String中
    对不对啊》?
    我也不知道!
    呵呵 
      

  3.   

    final String str2 = "length: "+pig.length(); 写错了
    -》
    final String str2 = "length: "+str1.length(); 
      

  4.   

    我理解错了
    String str1 = "haha";
    String str2 = "ha"+"ha";
    System.out.println(str1==str2);
    返回true;
    说明 + 操作符并没有生成新的对象,问题在str1.length()这里大家都说说吧!
      

  5.   

    好像有一个字符串池的概念,这个池维护所有不同的实例化后的字符串,比如,可能有a, ab, cde等等。当程序申请一个新的字符串的时候,如果这个字符串已经存在池中,那么这个字符串就会被返回,如果没有,就实例化一个新的,并且把它也放到池中。比如5楼说的,haha,因为ha + ha连接在一起后haha已经存在了,所以就返回原来的那个了,因此str1和str2是相同的。但是楼主说的两个字符串不同,所以有新的字符串被new出来吧。
      

  6.   

    一个字符串用+和一个对象相连就会自动调用这个对象的toString方法。所以final String str2 = "length: "+str1.length(); 其实是 Integer i = str1.length();

    final String str2 = "length: " + i.toString();的简写形式。
      

  7.   

    不是这样的吧.
        String a = "haha";
        String c = "ha";
        String b = c+"ha";
        System.out.println(a);
        System.out.println(b);
        System.out.print(a == b);
        这样打出来也是false
      

  8.   


    我的理解是 + 不会产生新对象。所以" "+" "的时候不会有问题。但是 " " + T 的时候,如果T是基本类型(这里是str.length的返回值),就会先自动装箱为一个对象,然后调用这个对象的toString方法。这个时候就有新的对象产生了,所以就会出现楼主遇到的情况。
      

  9.   

    至于池,这个概念要分两个来说。一个是string,另外一个是stringbuffer.两者有所不同。前者是池内有了还会生成,后者池内有了就不再生成了。
      

  10.   

    我同意楼上的意见final String str1 = "length: 10"; 
    final String str2 = "length: "+pig.length(); 这里的关键是pig.length(); 
    它调用length()方法之后,返回的是int类型的,在调用toString()方法,这时候应该创建一个新的对象,在堆里创建,所以你得到的结果为false,如下代码String str2 = "length: "+new Integer(pig.length()).toString(); 
      

  11.   


    String str2 = "length: "+10;
    10是int类型的啊,但是这样的话
    str1==str2为true所以我觉得 初始化必须是字面常量才可以,否则都会在堆中new一个新的对象
      

  12.   

    多个字符串相加,系统是使用StringBuilder 进行的,不是采用 new String();
      

  13.   

    这点忘了说了···int不能转换为String,所以在用 "length: "+10 的时候会先把 10 转为 "10"。然后字符串相加。
      

  14.   

    发现自己说的好乱···补充一下···10 是一个数值 ,不可能给 10 赋一个新值。换句话说是final的。在调用toString()的时候就不会产生对象然后使用动态绑定调用 String toString() 而是直接调用static String toString()。静态的··不需要对象··
      

  15.   

    连接操作符“+”可以被重载,使它可以操作String,pig.length()返回的是int,系统自动调用toString()方法把它变为String型,。之后就不知道了。感觉应该有新对象吧,不然那个String放在哪里啊? 
      

  16.   


    TIJ中明确说明,string的相加会被编译器优化为使用StringBuilder。
      

  17.   

    '+'上JAVA里面唯一的重载运算符。
      

  18.   


    JAVA池中存储的STRING是在编译时就产生的!
    所以"HAHA"=="HA"+"HA"(编译时能获得这"两"个STRING,并认为它们是一致的),但是C+"HA",在编译时是不会识别的,只有在运行时才能知道C+"HA"到底是什么,所以C+"HA"得到的STRING,已经不是在JAVA池中的STRING,C+"HA"!="HAHA"也就正常了
      

  19.   

    是的,希望这篇文章能帮到你.
     1  
     2StringBuffer   是线程安全的 
     3StringBuilder   不保证线程安全(在1.5中引入的),一般情况下比StringBuffer快
     4
     5一个String对象的长度是固定的,不能改变它的内容,或者是附加新的字符至String对象中。您也许会使用+来串联字符串以达到附加新字符或字符串的目的,但+会产生一个新的String实例。如果程序对这种附加字符串的需求很频繁,并不建议使用+来进行字符串的串联。在面向对象程序设计中,最好是能重复运用已生成的对象,对象的生成需要内存空间与时间,不断地产生String实例是一个没有效率的行为。   
     6J2SE   5.0提供java.lang.StringBuilder类,使用这个类所产生的对象默认会有16个字符的长度,您也可以自行指定初始长度。如果附加的字符超出可容纳的长度,则StringBuilder对象会自动增加长度以容纳被附加的字符。如果有频繁作字符串附加的需求,使用StringBuilder会让程序的效率大大提高。通过下面的简单测试程序就可以知道效能差距有多大。   
     7ü   范例6.5     AppendStringTest.java                                                                                                               
     8public   class   AppendStringTest   {   
     9        public   static   void   main(String[]   args)   {   
    10                String   text   =   "";   
    11
    12                long   beginTime   =   System.currentTimeMillis();   
    13                for(int   i   =   0;   i   <   10000;   i++)   
    14                        text   =   text   +   i;   
    15                long   endTime   =   System.currentTimeMillis();   
    16                System.out.println("执行时间:"   +   (endTime   -   beginTime));   
    17
    18                StringBuilder   builder   =   new   StringBuilder("");   
    19                beginTime   =   System.currentTimeMillis();   
    20                for(int   i   =   0;   i   <   10000;   i++)   
    21                        builder.append(String.valueOf(i));   
    22                endTime   =   System.currentTimeMillis();   
    23                System.out.println("执行时间:"   +   (endTime   -   beginTime));   
    24        }   
    25}   
    26
    27在范例6.5中首先使用+来串联字符串,使用System.currentTimeMillis()取得for循环执行前、后的系统时间,这样就可以得知for循环执行了多久。以下是我的计算机上的测试数据:   
    28
    29执行时间:4641   
    30执行时间:16   
    31可以看到执行的时间差距很大,这说明了使用+串联字符串所带来的负担。如果有经常作附加字符串的需求,建议使用StringBuilder。事实上就范例6.5来说,第二个for循环执行时间还可以更短,因为append()也可以接受基本数据类型,所以不必特地使用String.valueOf()方法从int取得String。改为以下的方式,执行时间可以大幅缩短:   
    32for(int   i   =   0;   i   <   10000;   i++)   
    33        builder.append(i);   
    34使用StringBuilder最后若要输出字符串结果,可以用toString()方法。可以使用length()方法得知目前对象中的字符长度,而capacity()可返回该对象目前可容纳的字符容量。另外,StringBuilder还有像insert()方法可以将字符插入指定的位置,如果该位置以后有字符,则将所有的字符往后移;deleteChar()方法可以删除指定位置的字符,而reserve()方法可以反转字符串。详细的使用可以查询java.lang.StringBuilder的API文件说明。   
    35StringBuilder是J2SE   5.0才新增的类,在J2SE   5.0之前的版本若有相同的需求,则使用java.lang.StringBuffer。事实上,StringBuilder被设计为与StringBuffer具有相同的操作接口。在单机非多线程(Multithread)的情况下使用StringBuilder会有较好的效率,因为StringBuilder没有处理同步(Synchronized)问题。StringBuffer则会处理同步问题,如果StringBuilder会在多线程下被操作,则要改用StringBuffer,让对象自行管理同步问题。
      

  20.   


    这个我一直没有想通,太感谢ssqmnlin 了。
      

  21.   

    支持29楼的说法,对于字符串常量:"HAHA"和"HA"+"HA" 编译时能获得这"两"个STRING,并认为它们是一致的;这应该类似于int a=10; int b=10;a==b is true; 相同点就在于都是常量,在程序运行前就分配了值。而且值是在栈里分配的吧,这个不清楚,总感觉与new的对象存放的位置不同。
      

  22.   

    是重新定义一个string对象,把两个连接的结果赋给他,原来的两个等待垃圾回收,如果修改频繁,建议使用stringbuilder
      

  23.   

    问:
    想知道连接操作符“+”的定义,他是否是new了一个新的字符串
    紫竹的是正解!答:我的看法不是这样,我认为是基于concat(...)方法实现的。
    理由:
    我记得James Gosling在他的第四版书中讲得很清楚:
    串的“+”与串的方法concat(...)是完全等价的。即:
    如下两行是完全等价的:
    newStr = oldStr.concat(" not");
    newStr = oldStr + " not";而: public String concat(String str) {
    int otherLen = str.length();
    if (otherLen == 0) {
        return this;
    }
    char buf[] = new char[count + otherLen];
    getChars(0, count, buf, 0);
    str.getChars(0, otherLen, buf, count);
    return new String(0, count + otherLen, buf);
        }并不是基于StringBuilder或StringBuffer的。
      

  24.   

    答:在JAVA的API文档中关于String类的一段话:
    Java 语言提供对字符串串联符号("+")和其他对象到字符串的转换的特殊支持。字符串串联是通过 StringBuilder(或 StringBuffer)类及其 append 方法实现的。字符串转换是通过 toString 方法实现的,该方法由 Object 类定义,并可被 Java 中所有类继承。有关字符串串联和转换的更多信息,请参阅 Gosling、Joy 和 Steele 合著的《The Java Language Specification》。 可是在合著的《The Java Language Specification》中我看到的是与str.concat(...)等价。有点乱。
    不过还是按API文档中的一段话理解
      

  25.   

    是,
    String s = "Hello world!";许多人都做过这样的事情,但是,我们到底声明了什么?回答通常是:一个String,内容是“Hello world!”。这样模糊的回答通常是概念不清的根源。如果要准确的回答,一半的人大概会回答错误。
    这个语句声明的是一个指向对象的引用,名为“s”,可以指向类型为String的任何对象,目前指向"Hello world!"这个String类型的对象。这就是真正发生的事情。我们并没有声明一个String对象,我们只是声明了一个只能指向String对象的引用变量。所以,如果在刚才那句语句后面,如果再运行一句:String string = s;我们是声明了另外一个只能指向String对象的引用,名为string,并没有第二个对象产生,string还是指向原来那个对象,也就是,和s指向同一个对象。
    你如果用+那肯定要在内存中创建一个新对象了
      

  26.   

    如果是2个字符串如"ASAS"和"FDFD"相连那可以用+
    但如果其中一个或2个都是变量那最好用StringBuffer 我之前都是这么做的
    关于上面所说的2个的原因和JAVA的内部机制有关 网上有很多解释自己可以去查一下
      

  27.   

    为了加深理解,我们可以来做几个小实验。javac Test         编译文件
    javap -c Test   查看虚拟机指令实验一:纯字符串
    public class Test {
        public static void main(String args[]) {
            String str = "a";
        }
    }   // 将字符串 a 存入常数池
       0:   ldc     #2; //String a
       // 将引用存放到 1 号局部变量中
       2:   astore_1
       3:   return实验二:纯字符串相加
    public class Test {
        public static void main(String args[]) {
            String str = "a" + "b";
        }
    }   // 将字符串 ab 压入常数池
       0:   ldc     #2; //String ab
       2:   astore_1
       3:   return实验二可以很明显地看出,编译器在编译时产生的字节码已经将 "a" + "b" 优化成了 "ab",
    同理多个字符串的相加也会被优化处理,需要注意的是字符串常量相加。实验三:字符串与自动提升常量相加
    public class Test {
        public static void main(String args[]) {
            String str = "a" + (1 + 2);
        }
    }   // 将字符串 a3 压入常数池
       0:   ldc     #2; //String a3
       2:   astore_1
       3:   return通过虚拟机指令可以看出,1 + 2 自动提升后的常量与字符串常量,虚拟机也会对其进行优化。实验二、实验三结论:常量间的相加并不会引起效率问题实验四:字符串与变量相加
    public class Test {
        public static void main(String args[]) {
            String s = "b";
            String str = "a" + s;
        }
    }   // 将字符串 b 压入常数池
       0:   ldc     #2; //String b
       // 将引用存放到 1 号局部变量中
       2:   astore_1
       // 检查到非常量的相加,这时创建 StringBuilder 对象
       3:   new     #3; //class java/lang/StringBuilder
       // 从栈中复制出数据,即把字符串 b 复制出来
       6:   dup
       // 调用 StringBuilder 的初始构造
       7:   invokespecial   #4; //Method java/lang/StringBuilder."<init>":()V
       // 将字符串 a 压入常数池
       10:  ldc     #5; //String a
       // 调用 StringBuilder 的 append 方法,把字符串 a 添加进去
       12:  invokevirtual   #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
       // 从 1 号局部变量中加载数据引用
       15:  aload_1
       // 调用 StringBuilder 的 append 方法,把字符串 b 添加进去
       16:  invokevirtual   #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
       // 调用 StringBuilder 的 toString 方法
       19:  invokevirtual   #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
       // 将 toString 的结果保存至 2 号局部变量
       22:  astore_2
       23:  return实验四可以看出,非常量字会串相加时,由于相加的变量中存放的是字符串的地址引用,
    因为在编译时无法确切地知道其他具体的值,也就没有办法对其进行优化处理,这时为了
    达到连接的效果,其内部采用了 StringBuilder 的机制进行处理(JDK 5 中新增的,我
    这里没有 JDK 1.4,估计在 JDK 1.4 下采用的是 StringBuffer),将他们都 append
    进去,最后用 toString 输出。若 s 为其他类型时,比如:int 类型,也是采用同种方式进行处理。同理,根据实验二的结果,在 String str = "a" + "b" + s; 时,先会优化成 "ab" 再与
    s 根据实验四的方式进行处理,这时 StringBuilder 仅调用了两次 append 方法。如果是 String str = "a" + s + "b"; 这种形式的就没办法优化了,StringBuilder 得调
    用三次 append 方法。实验四的结论表明,字符串与变量相加时在内部产生了 StringBuilder 对象并采取了一定
    的操作。如果只有一句 String str = "a" + s; 这样子的,其效率与
    String str = new StringBuilder().append("a").append(s).toString();
    是一样的。一般所说的 String 采用连接运算符(+)效率低下主要产生在以下的情况中:public class Test {
        public static void main(String args[]) {
            String s = null;
            for(int i = 0; i < 100; i++) {
                s += "a";
            }
        }
    }每做一次 + 就产生个 StringBuilder 对象,然后 append 后就扔掉。下次循环再到达时重
    新产生个 StringBuilder 对象,然后 append 字符串,如此循环直至结束。如果我们直接采用 StringBuilder 对象进行 append 的话,我们可以节省 N - 1 次创建和
    销毁对象的时间。
      

  28.   


    到底产不产生新对象阿????
    产生StringBuilder()对象??
      

  29.   

    字符串与变量连接时,当然要产生 StringBuilder 对象了,否则怎么进行操作啊,不过这一切都是编译器自己内部处理掉了。
      

  30.   

    产生,我第三次说了。StringBuffer不Buffer的,都是欲盖弥彰的,没有一个String对象,它引用谁啊?
    你们干吗不把toString方法也javap出来啊?
      

  31.   

    String str1 = "haha";
    String str2 = "ha"+"ha";
    System.out.println(str1==str2); 
      

  32.   


    String str1 = "haha"; //这里在编译期时就放到了池子里
    String str2 = "ha"+"ha";  // 这里会先拼成"haha" 然后去池子里找,如果找到了,就用,如果找不到,就new(分配内存)个新的,放入池中。
    这里能找到,所以下面这句为True
    System.out.println(str1==str2); //true 除了名字不一样外,其他都一样(内存地址)所以返回true
    String s1 = "ha" //这里同理也会到池里找,没有new一个新的放到池里,这里会放一个ha到池里。
    String s2 = "ha" //这里找,有,用池里的,同时s1,s2引用相同地址,除了名字不一样外,其他都一样final String str1 = "length: 10"; // 没有,放到池里。
    以上都在编译期做的事情,常量,会放到池子里。
    final String str2 = "length: "+str1.length(); //这里不是在编译期做的事情,是存在Heap中的。
    str1 和 str2 引用不同的地址,new一个"length: "+str1.length()放到Heap中,并用str2指向新地址。