常量池中两个String的引用ID

时间:2014-01-18 04:08:17

标签: java

访问String Constant Pool Java

public class StringLiterals {
    public static void main(String[] args) {
        String s1="This is ";
        s1=s1+"my book";
        String s2="This is my book";
        System.out.println(s1==s2);

    }
}

O / P:错误

期待O / P:真

5 个答案:

答案 0 :(得分:6)

也许这有助于澄清事情。

    String s1 = "This is";
    s1 = s1 + " my book"; // Note the space
    String s2 = "This is my book";
    String s3 = "This is my book";
    System.out.println(s1==s2); // False
    System.out.println(s2==s3); // True

“字符串只有在明确地或通过类使用文字时才放入池中。”因此,您不能使用+运算符连接字符串,并期望将其放入字符串常量池中。

答案 1 :(得分:3)

您的代码汇编成

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #16                 // String This is 
       2: astore_1      
       3: new           #18                 // class java/lang/StringBuilder
       6: dup           
       7: aload_1       
       8: invokestatic  #20                 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
      11: invokespecial #26                 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
      14: ldc           #29                 // String my book
      16: invokevirtual #31                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      19: invokevirtual #35                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      22: astore_1      
      23: ldc           #39                 // String This is my book
      25: astore_2      
      26: getstatic     #41                 // Field java/lang/System.out:Ljava/io/PrintStream;
      29: aload_1       
      30: aload_2       
      31: if_acmpne     38
      34: iconst_1      
      35: goto          39
      38: iconst_0      
      39: invokevirtual #47                 // Method java/io/PrintStream.println:(Z)V
      42: return   

相当于

public static void main(String[] args) {
    StringBuilder sb = new StringBuilder("This is ");
    sb.append("my book");
    String s1 = sb.toString();
    String s2 = "This is my book";
    System.out.println(s1 == s2);
}

因为

s1=s1+"my book";

不是常量表达式 - 您正在读取变量的值,编译器将假设您可以在此期间更改它。如果你想要那个

  

由常量表达式计算的字符串(第15.28节)在编译时计算,然后将其视为文字。 JLS (§3.10.5)

适用于您必须将代码更改为

public static void main(String[] args) {
    String s1 = "This is " + "my book";
    String s2 = "This is my book";
    System.out.println(s1 == s2);
}

public static void main(String[] args) {
    final String s1a = "This is ";
    final String s1b = "my book";
    String s1 = s1a + s1b;

    String s2 = "This is my book";
    System.out.println(s1 == s2);
}

现在你可以保证它有效。第二个例子编译成

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #16                 // String This is 
       2: astore_1      
       3: ldc           #18                 // String my book
       5: astore_2      
       6: ldc           #20                 // String This is my book
       8: astore_3      
       9: ldc           #20                 // String This is my book
      11: astore        4
      13: getstatic     #22                 // Field java/lang/System.out:Ljava/io/PrintStream;
      16: aload_3       
      17: aload         4
      19: if_acmpne     26
      22: iconst_1      
      23: goto          27
      26: iconst_0      
      27: invokevirtual #28                 // Method java/io/PrintStream.println:(Z)V
      30: return    

并且你可以看到加载2次字符串#20

答案 2 :(得分:2)

首先,你错过了一个空间。我认为这只是一个错误。

您可能已经看到过类似的内容:

"This is"+" my book" == "This is my book"

为什么这样做?因为它都是编译时常量 JLS 7 15.28。特别是“String类型的文字”和“添加运算符+和 - ”。

还有“简单名称[...]引用常量变量”。但这并不适用,因为您的变量不是final

但这不是你应该特别需要知道的事情。只需将equals用于String s。

答案 3 :(得分:0)

您不能使用==来比较两个字符串,因为==运算符断言s1和s2指向相同的内存位置,而不是内容相等。要比较两个字符串的内容以查看它们是否包含相同的内容,请使用String的.equals()方法。另外,s1=s1+行需要额外的空间。

代码:

{
public class StringLiterals {
public static void main(String[] args) {
    String s1="This is";
    s1=s1+" my book";
    String s2="This is my book";
    System.out.println(s1.equals(s2));

    }
}

如果你想使用==,那么你必须使用它:

public class StringLiterals
{
  public static void main(String[] args)
  {
    String s1 = "This is my book";
    String s2 = s1;
    System.out.println(s1 == s2);
  }
}

因为 Strings 是对象,它们的==行为与int,chars和其他原语不同。

答案 4 :(得分:-1)

+运算符的存在会导致新的String。这里s1 = s1 + " my book",s1 +“我的书”隐式创建新的String并存储其对s1的引用。所以它与s2不同