The following statements:
URLClassLoader ucl = (URLClassLoader) ClassLoader.getSystemClassLoader();
Class<URLClassLoader> uclc = ucl.getClass();
fail with error:
Type mismatch: cannot convert from Class<capture#2-of ? extends URLClassLoader> to Class<URLClassLoader>
Why do I need a cast, here?
I found several posts explaining why You can't do the reverse (assign T to a ), but that's (kind of) obvious and understood.
NOTE: I am coding this under eclipse Luna, so I don't know if it's a Luna Quirk or if there's something I really dont understand in generics.
Because actually
<? extends Type>
is a supertype of<Type>
! Let's follow the specification.4.10.2 Subtyping among Class and Interface Types:
4.5.1. Type Arguments of Parameterized Types:
We therefore know that since
? extends URLClassLoader
containsURLClassLoader
,Class<? extends URLClassLoader>
is a supertype ofClass<URLClassLoader>
.Because a narrowing reference conversion is not permitted within an assignment context, a compilation error occurs.
Also note that this means the reverse assignment is permitted:
Covariance vs contravariance vs invariance
Class<? extends URLClassLoader>
is invariant.As a result,
Class<? extends URLClassLoader>
is not a subtype ofClass<URLClassLoader>
In Java a variable can hold a reference of an instance of same type or subtype.
Hence,
is invalid.
On the other hand,
would be valid.