You're basically checking whether a string was already in the string pool. The string "java" isn't added to the pool by calling intern
in your first piece of code because it's already in the string pool. In each method, your code:
- Creates a new string
- Calls
intern
on the newly created string (but ignores the result; almost always a bad idea, and you can detect the existence of a previous value in the string pool easily by using the return value)
- Compares the new string with a string literal, which will always use the result that's now in the string pool
Now the call to intern
will add the target string to the pool if it doesn't already exist, so your comparison will return true if and only if the new string value was not previously in the string pool. This is equivalent to testing whether intern
returns a different reference to the target of the call.
For any given string reference, there are three possibilities:
- That exact reference is present in the string pool already. (That can't be the case in your code, because you're creating a new string.)
- A reference to an equal string is present in the string pool. In that case,
intern()
will return the existing reference.
- No equal string is present in the string pool. In that case, the target of the call will be added to the string pool, and the same reference returned.
What you're seeing is the result of other code putting things in the string pool - quite possibly as part of loading classes. Here's an example to demonstrate that:
public class Test {
public static void main(String... args) {
checkInterned("ja", "va");
checkInterned("ja", "va.lang");
checkInterned("ja", "va.other");
checkInterned("Int", "eger");
checkInterned("abc", "def");
checkInterned("Te", "st");
checkInterned("Te", "st2");
checkInterned("check", "Interned");
checkInterned("check", "Interned2");
}
public static void checkInterned(String start, String end) {
String x = start + end;
String y = x.intern();
System.out.println(x + " was interned already? " + (x != y));
}
}
Output:
java was interned already? true
java.lang was interned already? true
java.other was interned already? false
Integer was interned already? true
abcdef was interned already? false
Test was interned already? true
Test2 was interned already? false
checkInterned was interned already? true
checkInterned2 was interned already? false
So the interned values are:
java
java.lang
Integer
Test
checkInterned
They're all names that would naturally come up when loading classes (including the one being run).
I suspect that "java" is only a special case here in that there may well be lots of code within the JRE that checks whether a string starts with "java" as a reserved name.
This doesn't indicate anything about "java" being a keyword though - it's just "a string that's already in the string pool". You don't need to treat it any differently.