Strange String pool behavior

后端 未结 4 1844
旧时难觅i
旧时难觅i 2021-01-30 10:02

I\'ve got a question of some strange String pool behavior. I\'m using == to compare equal Strings to find out whether they\'re in the pool or not.

p         


        
相关标签:
4条回答
  • 2021-01-30 10:30

    In the second case the compiler COULD have recognized that + "" is a no-op of sorts, since "" is a compile-time value known to be zero length. But the compiler is still required to check the result from giveLiteralString for null (since the null check would occur as a result of the + operation in the non-optimized case), so it's simplest to just not attempt the optimization.

    As a result, the compiler generates code to perform the concatenation, and a new string is created.

    0 讨论(0)
  • 2021-01-30 10:32

    After decompiling this line

    System.out.println("555" == "555" + "");
    

    I got this bytecode

        LINENUMBER 8 L0
        GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
        ICONST_1
        INVOKEVIRTUAL java/io/PrintStream.println(Z)V
        ...
    

    which is equivalent to

      System.out.println(true);
    

    that means expression "555" == "555" + "" compiles to boolean true.

    For giveLiteralString() == giveLiteralString() + "" javac built this bytecode

        LINENUMBER 8 L0
        INVOKESTATIC Test1.giveLiteralString()Ljava/lang/String;
        NEW java/lang/StringBuilder
        DUP
        INVOKESTATIC Test1.giveLiteralString()Ljava/lang/String;
        INVOKESTATIC java/lang/String.valueOf(Ljava/lang/Object;)Ljava/lang/String;
        INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
        INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;
        IF_ACMPNE L1
        ...
    

    which is equivalent to

    if (giveLiteralString() == new StringBuilder(giveLiteralString()).append("").toString()) {
    ...
    

    which will always produce false since here we're comparing 2 disctinct objects.

    0 讨论(0)
  • 2021-01-30 10:46

    Compile Time Concatenation String computed by constant expression are done at compile time and treated as constants or literals means the value of the string or expression is known or evaluated at compile time hence the compiler can check the same value in string pool and the return the same string object reference.

    Runtime Concatenation String expressions whose values are known or can not be evaluated at compile but depends on the input or condition of run-time then the compiler will not know the value of the string and hence always land up using StringBuilder to append the string and always returns a new string . I guess this example will clarify it better.

    public static void main(String[] args) {
        new StringPoolTest().run();
      }
      String giveLiteralString() {
        return "555";
      }
    
      void run() {
        System.out.println("555" + 9 == "555" + 9);  
        System.out.println("555"+Integer.valueOf(9) == "555" + Integer.valueOf(9)); 
        System.out.println(giveLiteralString() == giveLiteralString());
        // The result of runtime concatenation is a fresh string.
        System.out.println(giveLiteralString() == giveLiteralString() + "");
      }
    
    0 讨论(0)
  • 2021-01-30 10:51
    "555" + ""
    

    is a compile-time constant, whereas

    giveLiteralString() + ""
    

    isn't. Therefore the former compiles into just the string constant "555" and the latter compiles into the actual method invocation and concatenation, resulting in a fresh String instance.


    Also see JLS §3.10.5 (String Literals):

    Strings computed by concatenation at run time are newly created and therefore distinct.

    0 讨论(0)
提交回复
热议问题