java 中字符串常量的串联

concatenation of string constants in java

在 C++ 中,据我所知,创建多行字符串的最佳规范方法是创建相邻字符串并让编译器在编译时连接它们,如下所示:

string s = "This is a very long string ...\n"
   " and it keeps on going...";

在 Java 中,我知道的唯一方法是连接:

String s = "This is a very long string ...\n" +
   " and it keeps on going...";

问题是,这会在运行时生成单个字符串,还是 java 实际上也在编译时连接?出现问题的原因是由于以下行为:

String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2); // this prints true, because the compiler
// generates only one "abc" object
String s3 = "a";
s3 += "bc";
System.out.println(s1 == s3); // false

Java 为每个字符串创建一个不可变对象,但会重用文字以提高性能。

这一行创建了一个不可变的字符串s1

String s1 = "abc"; 

将引用与 s1 相同的字符串文字,因为这是一个文字,可以由编译器优化。

String s2 = "abc"; 

这是一个身份比较,你问的是S1和S2是同一个对象,不是同一个字符串。由于编译器通过使两个对象引用相同的不可变字符串进行了优化,因此 returns 为真。

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

这会创建 2 个不可变字符串,然后在运行时创建第三个字符串。由于运行时不能保证它可以找到一个已经存在的字符串来有效地引用它只是创建一个新对象并创建一个新的不可变字符串 s3

String s3 = "a";
s3 = s3 + "bc";  

这是错误的,因为它们是两个独立的数据对象。

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

注意字符串相等 returns 正确,这里是我们如何比较字符串对象的内容,而不是对象位置。这是第一个比较检查身份,第二个检查是否相等。

 System.out.println(s1.equals(s3));

Java 知道为字符串连接过程的每一步创建数据对象是非常低效的。为了帮助 java hava StringBuilder api 执行更高效的连接。

 String s = "a";
 s += "b";
 s += "c";
 s += "d";
 s += "e";

导致创建“9”个字符串对象并将其写入内存...

 ("a", "b", "ab", "c", "abc", "d", "abcd", "e", "abcde")

字符串生成器有帮助

StringBuilder sb = new StringBuilder();
sb.append("a");
sb.append("b");
sb.append("c");
sb.append("d");
sb.append("e");

效率更高,因为它执行单个连接并导致更好的内存使用。

("a", "b", "c", "d", "e", "abcde")
String s3 = "a";
s3 += "bc";

等同于:

String s3 = "a";
s3 = new StringBuilder().append(s3).append("bc").toString();

因此它创建了 String 的新实例。

您甚至可以尝试:

String s = null;
s += null;
System.out.println(s); // prints "nullnull"