如果我使用实例方法,在连接方面是否存在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来得出这个结论。
答案 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)
首先,StringBuilder
是StringBuffer
ArrayList
到Vector
的内容:它应该是首选的,因为它不是同步的。
您的第一个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)
我认为在内存使用情况下两者都是相同的。