使用operator + vs使用stringbuffer进行字符串连接?

时间:2012-07-26 10:36:34

标签: java string

如果我使用实例方法,在连接方面是否存在b / w 1和2的差异。我的意思是在任何一种情况下,最终只会构造一个对象,即“abc”。只是我看到的区别是测试将位于permgen空间内,即使线程来自实例方法,但是一旦线程超出方法,x将被垃圾收集但是构造的对象数量的术语将是相同的。正确?

// option 1
String test="a"+"b"+"c";

// option 2  
StringBuffer x = new StringBuffer().append("a").append("b").append("c").toString()

我引用链接http://docs.oracle.com/javase/7/docs/api/java/lang/StringBuffer.html来得出这个结论。

6 个答案:

答案 0 :(得分:8)

首先请注意您链接的文档很旧。请注意,它适用于 Java 1.4.2

  

J2SE 1.4.2处于其Java技术寿命终止(EOL)过渡期。 EOL过渡期从2006年12月11日开始,将于2008年10月30日完成,届时J2SE 1.4.2将达到其使用寿命终止(EOSL)。

newer versions of the documentation中,此声明已被删除。但是,您应该注意另一个声明:

  

从JDK 5发布版开始,这个类已经补充了一个设计用于单个线程StringBuilder的等效类。 StringBuilder类通常应优先使用,因为它支持所有相同的操作,但速度更快,因为它不执行同步。


其次请注意,您引用的文档包含以下代码:

x = "a" + 4 + "c";

4不只是一个错字。您的示例不同,因为编译器会将代码转换为仅使用单个字符串文字。这两行是相同的:

x = "a" + "b" + "c"; 
x = "abc";

字符串文字将被实习。


但是在编译器不能只使用单个字符串文字的一般情况下,编译器会将第一个版本转换为第二个版本,但它会使用StringBuilder代替,因为它更有效。

答案 1 :(得分:5)

首先 - 使用StringBuilder代替StringBuffer,现在不推荐使用StringBuffer

对于你的问题,现在它并不重要,编译器自动将String concacenation转换为StringBuilder。

只有两种情况可以使用它。第一个是更好的代码可读性(例如,如果您正在构建像SQL查询一样的长字符串)。第二个,当你在循环中徘徊Strings时,编译器总是为每个遍历循环创建一个新的StringBuilder实例,所以要小心。

答案 2 :(得分:4)

首先,StringBuilderStringBuffer ArrayListVector的内容:它应该是首选的,因为它不是同步的。

您的第一个String完全在编译时构造,并存储为String文字。此文字在池中实现,test变量始终指向同一个String实例。

您的第二个代码段在运行时动态连接三个字符串文字。每次调用它时都会返回一个新的String实例。

答案 3 :(得分:4)

查看2个示例生成的字节码,第一个字符串转换为“abc”字符串文字,而第二个字符串调用StringBuilder方法。你可以用System.out.println(test == "abc");来测试它,它会输出真的。

   0: ldc           #2                  // String abc
   2: astore_1      
   3: new           #3                  // class java/lang/StringBuffer
   6: dup           
   7: invokespecial #4                  // Method java/lang/StringBuffer."<init>":()V
  10: ldc           #5                  // String a
  12: invokevirtual #6                  // Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
  15: ldc           #7                  // String b
  17: invokevirtual #6                  // Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
  20: ldc           #8                  // String c
  22: invokevirtual #6                  // Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
  25: invokevirtual #9                  // Method java/lang/StringBuffer.toString:()Ljava/lang/String;
  28: astore_2      

答案 4 :(得分:3)

在这种特殊情况下,你在编译时连接三个字符串文字,编译器将生成代码,就像你输入的一样:

String test="abc";

因此完全避免任何中间对象。

答案 5 :(得分:0)

我认为在内存使用情况下两者都是相同的。