以下声明中的差异

时间:2015-03-22 18:58:26

标签: java string declaration string-concatenation

我无法识别以下Java中Strings声明的区别。

假设我有两个字符串

String str1="one";
String str2="two";

之间有什么区别
String str3=new String(str1+str2);

String str3=str1+str2;

在上述两个声明中,str3的内容将为onetwo

假设我创建了一个新字符串

String str4="onetwo";

然后没有上述声明,

if(str4==str3) {
    System.out.println("This is not executed");
}

为什么str3str4没有引用同一个对象?

4 个答案:

答案 0 :(得分:5)

对于非编译常量字符串,

str1 + str2将被编译为
new StringBuilder(str1).append(str2).toString()。这个结果不会被放入,也不会从字符串池中获取(其中有实际的字符串)。

"foo"+"bar"的情况下,编译器知道他使用哪些值,这是不同的故事,因此他可以将此字符串连接一次以在运行时避免它。这样的字符串文字也将被实习。

所以String str3 = str1+str2;

相同
String str3 = new StringBuilder(str1).append(str2).toString();

String str3 = new String(str1+str2);

相同
String str3 = new String(new StringBuilder(str1).append(str2).toString());

同样,由方法产生的字符串(如substringreplacetoString)不会被实习。
这意味着您要比较两个不同的实例(存储相同的字符),这就是==返回false的原因。

答案 1 :(得分:3)

Java没有“这个变量如何获得值”的记忆,因此如果结果相同,使用哪种方法并不重要。

关于比较,如果将字符串与==进行比较,则需要比较内存中对象的地址,因为String不是原始数据类型,不是值。您必须使用if(str4.equals(str3))

答案 2 :(得分:3)

因为Java中的String是不可变的,所以编译器将优化并重用String文字。因此

String s1 = "one";
String s2 = "one";
s1 == s2; //true because the compiler will reuse the same String (with the same memory address) for the same string literal
s1 == "o" + "ne"; //true because "Strings computed by constant expressions are computed at compile time and then treated as if they were literals"
s3 = "o";
s1 == s3 + "ne"; //false because the second string is created a run time and is therefore newly created

有关参考资料,请参阅http://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.5

答案 3 :(得分:0)

字符串有点棘手,因为有一些努力来分享他们的表示。而且他们是不可改变的。 简短的回答是:除非您真的处于较低级别,否则不应使用“==”比较字符串。 即使它对你有用,对你的队友来说也是一场噩梦。

要获得更长的答案和一点娱乐,请尝试以下方法:

String s1= "a" + "b";
String s2= "a" + "b";
String s3=new String("a"+"b");

System.out.println(s1==s2);
System.out.println(s3==s2);

由于编译器的共享努力,您会注意到s1 == s2。 但是s2!= s3因为你明确要求一个新的字符串。

,你不可能做任何非常聪明的事情,因为它是不可改变的。