'java String == shown strange result
i know what is difference '==' with 'equals' and JVM String recycle in String Constant pool!
but this is some weird.
String m1 = "aa".getClass().getSimpleName();
String m2 = "String";
System.out.println("m1 = " + m1); // String
System.out.println("m2 = " + m2); // String
System.out.println(m1 == m2); // false... !!!
I wanted to see if constants in other classes could not be recycled, so I used strings in other classes as follows.
public class GenerateString {
public String foo() {
return "String";
}
}
public class Client {
public static void main(String[] args) {
GenerateString generateString = new GenerateString();
String m1 = generateString.foo();
String m2 = "String";
System.out.println("m1 = " + m1); // String
System.out.println("m2 = " + m2); // String
System.out.println(m1 == m2); // true
}
}
This, of course, caused true as expected. Why does false come out when I get the name of the class with reflection?
Solution 1:[1]
This is an implementation detail, but for a top level class, the result of getSimpleName() is the result of a substring operation, like
Class<?> cl = String.class;
String s = cl.getName();
s = s.substring(s.lastIndexOf('.') + 1);
Results of such string operations are never part of the string pool. So, to add it to the pool, an explicit invocation of intern() would be needed.
But intern() is not a cheap operation. This answer lists some of the problems, like requiring thread safe updates or (in case of the HotSpot JVM) having a fixed hash table size, hence becoming inefficient due to collisions when too many elements are added.
Since nothing is known about the caller’s intentions, it’s not known whether these costs would pay off. Prior to JDK 11, there was not even a caching so even String.class.getSimpleName() == String.class.getSimpleName() would evaluate to false. Now, there’s a cache (softly reachable, so it still could get garbage collected), but adding the string to the pool would still only pay off if there are other occurrences of string constants or explicitly interned strings of the same contents, which can not be assumed in advance.
This is a different situation with the qualified name or, more formally, the Binary Name to which the class will be permanently associated. This is the name used for lookups at class loaders and the likelihood of encountering Class.forName("full.qualified.ClassName") is higher than encountering the specific "ClassName" somewhere. This string is constructed by native code anyway, which goes a similar code path than the code resolving string constants.
So, String.class.getName() == "java.lang.String" always resolves to true with this implementation, but since this has not been specified in the documentation, you should not rely on it.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Holger |
