Details
-
Bug
-
Status: Open
-
Minor
-
Resolution: Unresolved
-
3.2, 3.5
-
None
-
None
-
Sun OpenJDK
Description
TypeUtils in lang.reflect provides convenient methods for creating objects of the interface Type. Those objects are defined by the following classes:
- ParameterizedTypeImpl (implements ParameterizedType)
- WildcardTypeImpl (implements WildcardType)
- GenericArrayTypeImpl (implements GenericArrayType)
Similarly, there are corresponding classes, which implement the same interfaces, defined in one's particular JDK. And it's these latter classes that are instantiated when you get objects of type Type via reflection. Let's call these the "internal Type implementations." In the case of Sun's OpenJDK, they are defined in package sun.reflect.generics.reflectiveObjects.
Each of the TypeUtils classes implements Object.equals(Object) in a general way that's compatible with the internal Type implementations. For example, if I access a field declared with type Map<String, Integer> and get its generic type, via Field.getGenericType(), then that will be equal to the TypeUtils object returned by:
TypeUtils.parameterize(Map.class, String.class, Integer.class)
That's what I'd expect, so that's great.
However, the TypeUtils classes implement their Object.hashCode() method in a different way from the corresponding implementations in Sun OpenJDK implementations. That's not so surprising, but it breaks the contract of Object.hashCode():
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
In other words, the two Type objects above will both consider themselves equals to each other, but they have different hash codes.
One example of a negative consequence of this problem is a collection class that implements its equality (to other collections) by checking hash codes of its elements, e.g., Guava's immutable collections. If you have Type objects in those collections, with TypeUtils Type objects in c1 and Sun OpenJDK Type objects in c2, you will see that c1.equals(c2) returns false – because their elements don't all have the same hash codes – even though those elements are all considered equal.