Question about casting a class in Java with generics
https://softwareengineering.stackexchange.com/questions/241157
-
03-10-2020 - |
Question
In Java 6
Class<? extends ArrayList<?>> a = ArrayList.class;
gives and error, but
Class<? extends ArrayList<?>> b = (Class<? extends ArrayList<?>>)ArrayList.class;
gives a warning.
Why is (a) an error? What is it, that Java needs to do in the assignment, if not the cast shown in (b)?
And why isn't ArrayList
compatible with ArrayList<?>
I know one is "raw" and the other is "generic", but what is it you can do with an ArrayList<?>
and not with an ArrayList
, or the other way around?
Solution
Well, a generic class is by definition not equal to a raw class. What you're trying there hides the issue of instantiation of ArrayLists (the actual lists, not their types).
ArrayList raw = new ArrayList();
will work and will allow any kind of element, objects, primitives, anything. On the other hand,
ArrayList<?> generic = new ArrayList<?>();
won't work since it's unclear, at compile time, what actual elements the list will hold. So, in order to make the list (almost) as broadly usable as the raw one, you could instantiate it like this:
ArrayList<?> generic = new ArrayList<Object>();
(That will only hold actual objects, though, no primitives.)
generic
and raw
will never be equal type-wise and it won't make sense for them to be equal.
What you can do with generic types instead of raw ones? Well, be safe at compile time. :) The other way around? Use primitives (generic types must inherit from Object
which primitives do not).
OTHER TIPS
While it's true that Java's type erasure means that generics are compiled into raw classes, they still mean something at compilation. The whole point of generics is to apply consistent casting at compile time, so it should be no wonder that you can't implicitly cast from Class<ArrayList>
to Class<? extends ArrayList<?>>
even though they are exactly the same type at runtime.
In other words - you get a compilation error because the whole point of generics in Java is to provide safe implicit "casting" in such cases, and raise a compilation error when there is a generic type mismatch.