Consider a code:
public class GenericsConfusion {
public static <T> Class<T> get(Class<T> clazz) {
Map<Class, Class> map = new HashMap<Class, Class>();
map.put(Integer.class, String.class);
return map.get(clazz);
}
public static void main(String[] args) {
Class<Integer> clazz = get(Integer.class);
System.out.println(clazz);
}
}
It compiles and runs perfectly. The idea was to return in get method the class which has the same type parameter as input class. But it is broken due to the presence of map.
Yes, I know that in runtime the type parameter information is erased, so without the type parameters this code is perfectly valid. Also I know I can fix it by specifying Map<Class<T>, Class<T>>
But the fact is that in method signature I have type parameters, and they dont help me in compile time.
Is this a misuse of some concept?
Or it is a disadvantage of Java generics?
Or its perfectly ok and I misunderstand the idea of type parameters?
A raw type, such as Class
or Map
(as opposed to Class<...>
or Map<..., ...>
), circumvents the type-checking of generics. You can even write something like this:
final Class<Integer> whoops = (Class) String.class;
This is an unfortunate weakness in the type system. It was originally included in Java 5 (which introduced generics) for compatibility with code written under previous versions.
For the most part, you can avoid this weakness by avoiding the use of raw types. Your compiler should warn you about them.
Unfortunately, there are various circumstances where raw types are essentially unavoidable (due to the special typing of .getClass()
; due to the fact that we can only write (for example) Map.class
and not Map<String, String>.class
(or Map.<String, String>class
); due to erasure and reflection, etc.); but happily, as you've noted, your circumstance does not appear to be one of these.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With