| For the record, java.util.Map does not extend java.util.Collection. The root of the problem is that TypeUtils.getCollectionClass declares it returns a Class<? extends Collection>, but this may in fact be a Class<Map> that has been casted brutally, because{{TypeUtils.isCollectionClass}} returns true for Map.class:
public static Class<? extends Collection> getCollectionClass(Type type) {
return new TypeSwitch<Class<? extends Collection>>() {
@Override
@SuppressWarnings("unchecked")
public Class<? extends Collection> caseClass(Class clazz) {
return isCollectionClass( clazz ) ? (Class<? extends Collection>) clazz : null;
}
}.doSwitch( type );
}
private static boolean isCollectionClass(Class<?> clazz) {
return clazz == Collection.class
|| clazz == java.util.List.class
|| clazz == java.util.Set.class
|| clazz == java.util.Map.class
|| clazz == java.util.SortedSet.class || clazz == java.util.SortedMap.class; }
From what I can see, the issue spread to those methods:
- org.hibernate.annotations.common.reflection.java.JavaXCollectionType.getCollectionClass()
- org.hibernate.annotations.common.reflection.java.JavaXMember.getCollectionClass()
At runtime, this probably has little impact, especially because the weirdness is taken into account in all Hibernate code, but potentially this could lead to really strange behavior. And, obviously, this makes client code harder to understand (why take Map.class into account when one is manipulating a Class<? extends Collection>?) A trivial solution would be to remove the bound (use Class<?> instead of Class<? extends Collection>), but this would break client code. Maybe 6.0 would be a good time for that? Also, using a different term than "Collection" (like "Container" or "MultiValued") may help avoid that kind of issue in the future. But that would require an even bigger API break. |