Difference between addition of String Literals and String objects

后端 未结 4 1874
忘掉有多难
忘掉有多难 2021-01-14 10:23

What is the difference between an addition of String Literal and String Object?

For example

    String s1 =\"hello\";
    String s2 =\"hello1\";
             


        
4条回答
  •  再見小時候
    2021-01-14 10:56

    EDIT: I assume that you know that you are comparing references, not the contents of the strings. If no, s3.equals(s5) is what you are looking for (as already mentioned).

    s3 is optimized by the compiler to "hellohello1" which is reused for s4 as well. I'm quite surprised that the compiler isn't smart enough to do the same for s5 though. Which JDK version are you using?. This optimization is only allowed for constant expressions (see 15.28 of Java Language Specification). In other words, any assignment to a non-final variable denies the possibility of later optimization.

    Here's the output of javap -c -l of a simple class that wraps your code into a main method (not that anybody asked for it, but I'm curious myself). So let's see what's going on:

    public static void main(java.lang.String[]);
      Code:
        0:  ldc #16; //String hello
        2:  astore_1
        3:  ldc #18; //String hello1
        5:  astore_2
        6:  ldc #20; //String hellohello1
        8:  astore_3
        9:  ldc #20; //String hellohello1
        11: astore  4
        13: new #22; //class java/lang/StringBuilder
        16: dup
        17: aload_1
        18: invokestatic    #24; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
        21: invokespecial   #30; //Method java/lang/StringBuilder."":(Ljava/lang/String;)V
        24: aload_2
        25: invokevirtual   #33; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        28: invokevirtual   #37; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        31: astore  5
        33: getstatic   #41; //Field java/lang/System.out:Ljava/io/PrintStream;
        36: aload_3
        37: aload   4
        39: if_acmpne   46
        42: iconst_1
        43: goto    47
        46: iconst_0
        47: invokevirtual   #47; //Method java/io/PrintStream.println:(Z)V
        50: getstatic   #41; //Field java/lang/System.out:Ljava/io/PrintStream;
        53: aload_3
        54: aload   5
        56: if_acmpne   63
        59: iconst_1
        60: goto    64
        63: iconst_0
        64: invokevirtual   #47; //Method java/io/PrintStream.println:(Z)V
        67: getstatic   #41; //Field java/lang/System.out:Ljava/io/PrintStream;
        70: aload   4
        72: aload   5
        74: if_acmpne   81
        77: iconst_1
        78: goto    82
        81: iconst_0
        82: invokevirtual   #47; //Method java/io/PrintStream.println:(Z)V
        85: return
    
    LocalVariableTable: 
      Start  Length  Slot  Name   Signature
       0     86      0     args   [Ljava/lang/String;
       3     83      1     s1     Ljava/lang/String;
       6     80      2     s2     Ljava/lang/String;
       9     77      3     s3     Ljava/lang/String;
      13     73      4     s4     Ljava/lang/String;
      33     53      5     s5     Ljava/lang/String;
    
    
    }
    

    I'm not to experienced reading byte code, but I'll give it a go :)

    • numbers starting with # (e.g. #16) are references to the constant pool. The content is always added as a comment to this line
    • ldc #16 followed by astore_1 means "load constant #16 and store it in slot 1". As you can see, this is done 4 times at the beginning for slots 1 - 4 which translates to s1, s2, s3 and s4 (see LocalVariableTable).
    • for s5, without going into much detail, there is obviously a StringBuilder and loading of slot 1 (aload_1) and slot 2 (aload_2) involved before storing the result in slot 5 (astore 5).

提交回复
热议问题