2013-01-21 27 views
16

我有两个问题:泳池何时更换?

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"); 
} 
  • 为什么s1s2指向同一个对象,而s1s3不? (没有使用new关键字)。

  • 如果我得到来自用户的字符串,并添加到上面这几行代码:

    BufferedReader in=new BufferedReader(new InputStreamReader(System.in)); 
    String name=in.readLine(); 
    if(name.equals("test")) 
        s1 = s1 + "xyz"; 
    

    如果用户输入xyz程序将打印Not equal,当用户输入另一件事方案产出Equal 。这是否意味着通过执行整个程序池会改变?优化器是否在编译时工作,并且继续在runtime中工作?

回答

15

为什么s1和s2指向同一个对象,而s1和s3不是? (没有使用新的关键字)。

因为连接发生在编译时,所以完成的字符串因此进入常量池,与第一个例子相同。这是编译器“已知”的特例。这确实意味着如此长的字符串,通过几条线连接在一起,仍然可以获得与简单字符串常量相同的性能改进。

在第二个示例中,您在运行时执行计算,因此它不会成为常量池的一部分。

但是请注意,在JLS中,字符串常量池中可以和不可以进入的细节有意留下含混,因此不同的实现可能会以不同的方式进行优化。它规定了哪些去那里的某些规则,但不要依赖这种行为在实现中保持一致。

9

为什么S1和S2都指向同一个对象,而S1和S3 不? (没有使用新的关键字)。

由于String在Java中是Immutable,所以String类的任何方法将返回一个新的String对象(也有一些例外,但 - 一个是substring方法)。因此concat方法会创建一个新字符串,该字符串将转至堆堆,并且不会添加到常量池中。

至于的s1s2的情况而言,两个串都在已知编译时间,因此它们是相同的字符串文字。

注意,置运算在第二字符串: -

String s2 = "b" +"l" + "a"; 

在编译时被评估,结果被称为是与第一串,和一个条目到恒定制成池。

3

有时(编译器使用字符串池时,编译器使用字符串池时,编译器会在运行时显示字符串的值),而在其他情况下则不会。

其实你的代码不应该依赖于使用或不使用池的事实。

你不能总是运行为主,所以如果你想看看你的字符串是从池中使用,你可以用javap的上市编译的代码是相对不言自明的。

相关问题