So I assume the String "java" is already in the String Literal Pool (for some reason) and therefore b.intern() returns a reference to that String without having to add String "java" to the String Literal Pool.
And just out of curiosity I've tried the same with a few other keywords from the method signature:
String b="ar".concat("gs"); => true
String b="ma".concat("in"); => false
String b="pub".concat("lic"); => true
So for String "main" you'll have the same output as for String "java".
Roel De Nijs wrote:...I assume the String "java" is already in the String Literal Pool (for some reason) and therefore b.intern() returns a reference to that String without having to add String "java" to the String Literal Pool.
I doubt that the string "java" is already in the String Literal Pool since the API documentation for the intern() method says that the pool is initially empty.
A pool of strings, initially empty, is maintained privately by the class String.
I suspect that the reason why the code snippets return false and true is that when we call b.intern(), the only guarantee the API makes is that b.intern() will return a string from the pool. The API does not guarantee that b will refer to a string in the pool.
The API documentation for the intern() method says:
Returns:
a string that has the same contents as this string, but is guaranteed to be from a pool of unique strings.
In order to ensure that the code snippets return true and true and ensure that b refers to a string in the pool, we must add
Daniel Cox wrote:I doubt that the string "java" is already in the String Literal Pool since the API documentation for the intern() method says that the pool is initially empty.
I know the pool is empty, but that doesn't mean the String "java" can't be added for any reason...
Daniel Cox wrote:I suspect that the reason why the code snippets return false and true is that when we call b.intern(), the only guarantee the API makes is that b.intern() will return a string from the pool. The API does not guarantee that b will refer to a string in the pool.
From the same API you have quoted earlier:
Meaning if the String "java" does not yet exist in the pool (as in the 2nd example), the String object (also refered to by b) is added to the pool and that reference is returned and assigned to c, resulting b and c having the same reference.When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned.
Roel De Nijs wrote:I know the pool is empty, but that doesn't mean the String "java" can't be added for any reason...
Sorry I misunderstood you

Roel De Nijs wrote:...resulting b and c having the same reference.
Yes, b and c have the same reference in the 2nd example, but the coding is wrong which is why b and c do not have the same reference in the 1st example. The code String c=b.intern() guarantees that c refers to the string "java" in the pool but does not guarantee that b refers to the same string "java" in the pool as demonstrated by the 1st example. One way to guarantee this is b=b.intern().
Daniel Cox wrote:The code String c=b.intern() guarantees that c refers to the string "java" in the pool but does not guarantee that b refers to the same string "java" in the pool as demonstrated by the 1st example.
That's in fact the beauty of this question... If the String "java" was not yet in the String Literal Pool, the String "java" would be added to the String Literal Pool and that reference would be returned resulting in b and c referring to the same object (according to the javadoc of the intern() method and illustrated with the 2nd code snippet). Because another reference is returned (resulting in printing false when comparing b and c) means the String "java" was already in the String Literal Pool.Why is "java" (and "main") already in the String Literal Pool

Roel De Nijs wrote:Why is "java" (and "main") already in the String Literal Pool
Because as you said earlier, when intern() runs
the string "java" will be added to the pool (if it is not already there).
Roel De Nijs wrote:If the String "java" was not yet in the String Literal Pool, the String "java" would be added to the String Literal Pool and that reference would be returned resulting in b and c referring to the same object (according to the javadoc of the intern() method and illustrated with the 2nd code snippet).
I think that the statement "resulting in b and c referring to the same object" is wrong. When intern() runs
the API says that the string "java" will be added to the pool (if it is not already there). The API then says that a reference to the string in the pool will be returned; implying that c will refer to the string "java" in the pool. The API does not guarantee that b will refer to the string "java" in the pool.
-
3
-
-
-
-
A short scan of the loaded classes for a Java9 version (obtained by using -verbose:class) shows, that two of the loaded classes contain the literals:
java.lang.VersionProps - contains "java", reason for "java" being interned (static field initializer contains the literal, class is initialized in init phase 1)
sun.launcher.LauncherHelper - contains "java" and "main", reason for "main" being interned (method for the main-method validation contains the literal)
The used code to scan the classes for the literals:
Daniel Cox wrote:I think that the statement "resulting in b and c referring to the same object" is wrong.
No, it's not! Based on the javadoc of the intern() method that's guaranteed if and only if the String object was not yet in the String Literal Pool. And the reason why it's guaranteed is mentioned in the javadoc of the intern() method (which I've quoted in one of my previous post)Assuming String "daniel" is not yet in the String Literal Pool, this is what happens (in a simplified version). The String object is created and reference 1979 is stored in variable b. When b.intern() is invoked, the JVM checks if the String "daniel" is already in the String Literal Pool. But it's not (according to our assumption). So that means the String "daniel" will be added to the String Literal Pool (e.g. POOL[counter++] = this;) and that reference (1979) is returned (which is assigned to c). So now you have three reference variables refering to the same String object: b, c and POOL[0] (assuming no other strings were already added to the pool).
A very simplified version of the intern() method would look like this
Roel De Nijs wrote:So now you have three reference variables refering to the same String object: b, c and POOL[0] (assuming no other strings were already added to the pool).
You're assuming that b.intern() implies that b will refer to a string in the pool. This is not correct.
The way to guarantee that b refers to a string in the pool is b=b.intern()
If your assumption was correct, this code will print true. It prints false because a refers to the string "jack" in the pool but b does not refer to the same string in the pool.
This code prints true because a and b refer to the string "jack" in the pool.
Daniel Cox wrote:@Tobias - some ranchers might be interested in making your code compile.
As Tobias mentioned you'll probably need JDK9 to successfully compile his code snippet. But it would be indeed interesting to know if the used class constants are defined somewhere in the Java API or are custom defined (and if so, to which values).
Daniel Cox wrote:
Roel De Nijs wrote:So now you have three reference variables refering to the same String object: b, c and POOL[0] (assuming no other strings were already added to the pool).
You're assuming that b.intern() implies that b will refer to a string in the pool. This is not correct.
I wonder why you only quote one sentence from a three line (on my computer) paragraph - therefore get rid of all context I've provided (which is very important here) - and tell me I am wrong

I have never said in this entire thread (nor in any other thread on this website) that any invocation of the intern() method will always result in three reference variables refering to the same String object. Never! Because that would simply be incorrect as mentioned in the javadoc of the intern() method (and also illustrated in your code snippets).
The only thing I've said: if and only if the String object is not yet present in the String Literal Pool (and this is the context you simply got rid of) and then you call the intern() method (like in the code snippet with "ja" and "ck" in the OP's 2nd code snippet), you will have three reference variables refering to the same String object: b, c and POOL[someIndex]. And that's actually guaranteed behavior (mentioned in the javadoc of the intern() method, also quoted by me somewhere in this topic).
And of course I know it's hard (if not impossible) to know if a String is already in the String Literal Pool (certainly in very large applications as many classes with String literals will be loaded to run the application), but that's completely irrelevant here. In this very simple code snippet we all know that the String object "jack" is not yet in the String Literal Pool when the intern() method is invoked.
-
3
-
-
-
-
The following code requires Java9 and compiles; the same is possible with Java8 (with the corresponding classes of sun.* instead of jdk.internal.* - simply replace #getTagAt with a try-catch block, obtain the unsafe instance via reflection and change the regex to match the verbose:class output).
Roel De Nijs wrote:I wonder why you only quote one sentence from a three line (on my computer) paragraph - therefore get rid of all context I've provided (which is very important here) - and tell me I am wrong
Sorry about this. Having gone through your post in greater detail, I see your point.

@Tobias - Thanks for pointing out why "java" and "main" are already in the pool.
