以下声明的差异

Difference in the following declarations

我无法识别 Java 中以下字符串声明的区别。

假设我有两个字符串

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

有什么区别

String str3=new String(str1+str2);

String str3=str1+str2;

在以上两个声明中,str3的内容将是onetwo

假设我创建一个新字符串

String str4="onetwo";

然后在上面声明的none中,

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

为什么 str3str4 指的不是同一个对象?

Java 没有 "how this variable got the value" 的记忆,因此如果结果相同,使用哪种方法并不重要。

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

因为 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

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)不会被保留。
这意味着您正在比较两个不同的实例(存储相同的字符),这就是为什么 == returns false.

字符串有点棘手,因为需要付出一些努力来分享它们的表示形式。另外,它们是不可变的。 简短的回答是:除非你真的在低级别工作,否则你不应该使用“==”比较字符串。 即使它对你有效,但对你的队友来说也是一场噩梦。

要获得更长的答案和一点乐趣,请尝试以下操作:

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 因为您已经明确要求一个新字符串。 你不太可能用它做任何非常聪明的事情,因为它是不可变的。