我有两个问题:
public static void main(String[] args) {
String s1 = "bla";
String s2 = "b" +"l" + "a";
String s3 = "b".concat("l").concat("a");
if(s1 == s2)
System.out.println("Equal");
else
System.out.println("Not equal");
if(s1 == s3)
System.out.println("Equal");
else
System.out.println("Not equal");
}
Run Code Online (Sandbox Code Playgroud)
为什么s1
和s2
指向同一个对象,而s1
和s3
不?(没有使用new
关键字).
如果我从用户那里得到一个字符串并将以下代码添加到上面的代码中:
BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
String name=in.readLine();
if(name.equals("test"))
s1 = s1 + "xyz";
Run Code Online (Sandbox Code Playgroud)
如果用户输入xyz
程序将打印Not equal
,当用户输入另一个程序输出时Equal
.这是否意味着池通过执行整个程序而改变?优化器是否在编译时工作runtime
并继续在?
Mic*_*rry 15
为什么s1和s2指向同一个对象,而s1和s3不指向?(没有使用新关键字).
因为连接发生在编译时,因此完成的字符串在常量池中与第一个示例中相同.这是编译器"已知"的特殊情况.它的确意味着长串,以这种方式连接多行,仍然可以获得与简单字符串常量相同的性能改进.
在第二个示例中,您在运行时执行计算,因此它不会成为常量池的一部分.
但请注意,在JLS中,有意和无法进入字符串常量池的细节是故意模糊的,因此不同的实现可能以不同的方式进行优化.它规定了一定的规则,什么都有去那里,但不依赖于这种行为是在不同的实现是一致的.
为什么s1和s2指向同一个对象,而s1和s3不指向?(没有使用新关键字).
因为String
在Java中Immutable
,所以字符串类的任何方法都将返回一个新的String对象(虽然有一些例外 - 一个是substring
方法).因此,concat
方法创建一个新的字符串,该字符串将转到堆,而不会添加到常量池中.
至于的情况下s1
,并s2
来讲,两个字符串在已知的编译时间,因此它们是相同的字符串文字.
请注意第二个字符串中的串联操作: -
String s2 = "b" +"l" + "a";
Run Code Online (Sandbox Code Playgroud)
在编译时进行求值,并且已知结果与第一个字符串相同,并且对常量池进行一个条目.