-4

Just run the below codes in jdk1.8(mine is jdk1.8.0_60), the result is:

true
false
true,

The method c2() returns false, why?

I just want to know about the runtime constant pool. Not about comparing different strings.

Attempt

public static void main(String[] args) throws InterruptedException {
        c1();
        c2();
        c3();
    }

    private static void c1() {
        String s1 = new String("a") + new String("b");
        s1.intern();
        String s2 = "ab";
        System.out.println(s1 == s2);
    }

    private static void c2() {
        String s1 = new String("h") + new String("e");
        s1.intern();
        String s2 = "he";
        System.out.println(s1 == s2);
    }

    private static void c3() {
        String s1 = new String("e") + new String("h");
        s1.intern();
        String s2 = "eh";
        System.out.println(s1 == s2);
    }
Emma
  • 27,428
  • 11
  • 44
  • 69
Mr.H
  • 1
  • 3
  • 1
    **Never** call `new String`. Never compare references with `==`. – Elliott Frisch Jun 28 '20 at 07:57
  • Why would this be a bug? This is entering the realms of undefined. Also, you might want to update your jdk. – matt Jun 28 '20 at 07:59
  • I just want to know about the runtime const pool. Not about comparing different string. – Mr.H Jun 28 '20 at 07:59
  • 1
    You know calling `x.intern()` doesn't necessarily make the string object `x` an interned string. It _returns_ an interned instance of the string. – khelwood Jun 28 '20 at 08:01
  • Have you read the javadoc for String#intern? You seem to be using it incorrectly. – matt Jun 28 '20 at 08:01
  • 2
    As an aside: I would suggest it's a bad idea to assume that any behavior you don't understand is likely to be a bug. (The title of the post starting "a jvm bug?".) Always assume that it's a failing on your part (of understanding or of code) until you can prove otherwise. Almost every bug I've ever encountered was my own fault, and I suspect most developers have the same experience - proceeding with that *expectation* is much more helpful than assuming that every problem is someone else's fault. – Jon Skeet Jun 28 '20 at 08:07
  • @Jon Skeet All right. Sorry. I just want to attact your foucs. Now I have changed it – Mr.H Jun 28 '20 at 08:17
  • 1
    @Mr.H: You mean you use "a jvm bug?" as clickbait, effectively? Please don't do that again. – Jon Skeet Jun 28 '20 at 08:29

1 Answers1

4

All you're detecting here is that by the time you reach your main method, "he" is already in the constant pool, but "ab" and "eh" aren't.

Therefore while c1 and c3 add your "new" strings to the constant pool when you call intern, in c2 the existing string is returned by intern - so if you change your code to

private static void c2() {
    String s1 = new String("h") + new String("e");
    s1 = s1.intern();
    String s2 = "he";
    System.out.println(s1 == s2);
}

... you'll see that prints true.

Alternatively, to make c1 print false, just force "ab" into the constant pool to start with:

public static final String foo = "ab";

Now "ab" is in the constant pool before c1 runs, so again, s1.intern() doesn't add anything to the constant pool, and the reference comparison prints false.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194