When generics were first introduced, getClass returned Class<? extends X> Class<? extends X> Class<? extends X> Class<? extends X> , where X is the static type of expression on which it was called. This led to unreasonable compilation problems, as reported in this Oracle error . Here is an example error report:
The following code fragment does not compile
void f(List<Integer> li, List<String> ls) { if (li.getClass() == ls.getClass()) ; }
because the intersection of Class<List<Integer>> and Class<List<String>> empty.
This problem was resolved by expanding the return type of getClass as it is now. From the documentation :
The actual type of result is Class<? extends |X|> Class<? extends |X|> Class<? extends |X|> Class<? extends |X|> where |X| erases the static type of the expression on which getClass is invoked.
This resolved the above question, but therefore led to what your question indicates. Soon after, another error was reported stating the following:
I think the input rule getClass() can be changed to Class<? extends wildcard(T)> Class<? extends wildcard(T)> Class<? extends wildcard(T)> Class<? extends wildcard(T)>
The wildcard operation is defined as follows: if the parameter T parameterized, wildcard(T)=erasure(T)<?> Else, wildcard(T)=T
JUSTIFICATION:
This rule introduces a raw type. The raw type should only be used to interact with legacy code.
The new rule introduces a wildcard. The relationship between a parameterized type and a wildcard is based on subtyping rules. The relationship between a parameterized type and a wildcard is based on the conversion of the original type.
This error did not work and remains open to this day, with the following counterarguments:
The sentence means getClass() will return Class<? extends ArrayList<?>> Class<? extends ArrayList<?>> Class<? extends ArrayList<?>> Class<? extends ArrayList<?>> an object that is incompatible with another Class<? extends ArrayList<?>> Class<? extends ArrayList<?>> Class<? extends ArrayList<?>> Class<? extends ArrayList<?>> Class<? extends ArrayList<?>> objects Class<? extends ArrayList<?>> . This is compatible with existing code, for example:
List<String> l = ...; Class<? extends List> c = l.getClass();
because the new type is RHS, Class<? extends List<?>> Class<? extends List<?>> Class<? extends List<?>> Class<? extends List<?>> , is a subtype of Class<? extends List> Class<? extends List> Class<? extends List> Class<? extends List> .
The disadvantage of enriching a class type argument is that it violates the idiomatic use of Class.cast . Today you can write:
List<Integer> x = ...; Class<? extends List> cl = x.getClass(); List<Integer> y = cl.cast(null);
and get a warning in cast() due to an unchecked conversion from List to List<Integer> . But with the sentence, the similar code does not compile:
List<Integer> x = ...; Class<? extends List<?>> cl = x.getClass(); List<Integer> y = cl.cast(null);
because the List<?> returned by cast() cannot be converted to List<Integer> . The only way to avoid the error is to cl.cast(..) before List and transfer the warning about unverified conversion to List<Integer> . This is actually what getClass() does.
In general, the proposal seems to be a good idea, but it has moderate complexity and a rather small gain.
(shortened and corrected with some typos)