Why does the String.intern() method return two different results? [duplicate]
Asked Answered
Y

2

9

I have the code like this:

String str1 = new StringBuilder("计算机").append("软件").toString();
System.out.println(str1.intern() == str1); //true

String str2 = new StringBuilder("ja").append("va").toString();
System.out.println(str2.intern() == str2); //false

String str3 = new StringBuilder("Str").append("ing").toString();
System.out.println(str3.intern() == str3); //true

I can understand why str1.intern() == str1 and str3.intern() == str3 are true, but I don't understand str2.intern() == str2. Why this is false?

My java version is: 1.8.0_73

Yahairayahata answered 17/3, 2016 at 14:25 Comment(2)
because "java" is obviously already in the constant pool, so str2.intern() just returns that reference, which is different from the new str2 reference.Prosecutor
@Prosecutor Why the "java" already in the constant pool? and why "String" is not?Yahairayahata
L
17

String.intern() returns a String in the string literal pool. However if the string already exists in the pool, it will return the existing String.

If you pick a new String, it should return the String you created, but if you use a String which happens to exist in the pool already you will get the existing String.

It is reasonable to assume that in this case "java" already exists in the pool so when you call intern() it returns a different object so == is false.

note: string.intern().equals(string) should always be true.

Luxor answered 17/3, 2016 at 14:29 Comment(8)
But how does that answer the question? I mean, it does not explain the above behavior.Hallowed
@user2004685 How doesn't it?Prosecutor
@user2004685 For strings == compares the reference not the contents.Luxor
It is reasonable to assume that in this case "java" already exists in the pool so when you call intern() it returns a different object so == is false. Now this make sense to me. Thanks!Hallowed
@PeterLawrey But I don't konw why the "java" already in and why "String" is not?Yahairayahata
@李思聪 you would need to check all the code which is run before this. By the time your program starts, it creates around 10,000 Strings.Luxor
@李思聪 That is different question (related but different from the one you asked). Simple answer is "because it wasn't placed there while starting JVM". If you want to see content of pool you could try using something like #22094611.Rask
@李思聪 At a guess, this class is used on startup to launch the program docjar.com/html/api/com/sun/tools/jdi/… and on line 125 there is the String literal "java"Luxor
M
4

The constant String "java" already exists in the Java constant pool, but you can verify that by changing

String str2 = new StringBuilder("ja").append("va").toString();
System.out.println(str2.intern()==str2);

to

String str2 = new StringBuilder("ja").append("va").toString();
System.out.println(str2.intern() == "java");

which will get the same constant and output

true

Alternatively, you could add "计算机软件" and "String" to the constant pool like

String a = "计算机软件";
String b = "String";
String str1 = new StringBuilder("计算机").append("软件").toString();
System.out.println(str1.intern() == str1);

String str3 = new StringBuilder("Str").append("ing").toString();
System.out.println(str3.intern() == str3);

Then you would get (consistent with your observations)

false
false
Meyer answered 17/3, 2016 at 14:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.