问题
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.
回答1:
Covariance vs contravariance vs invariance
Class<? extends URLClassLoader>
is invariant.
As a result,
Class<? extends URLClassLoader>
is not a subtype of Class<URLClassLoader>
In Java a variable can hold a reference of an instance of same type or subtype.
Hence,
Class<URLClassLoader> uclc = ucl.getClass();
is invalid.
On the other hand,
Class<? extends URLClassLoader> uclc = ucl.getClass();
would be valid.
回答2:
Why can't assign I <? extends Type> to <Type>?
Because actually <? extends Type>
is a supertype of <Type>
! Let's follow the specification.
4.10.2 Subtyping among Class and Interface Types:
Given a generic type declaration C<F1,...,Fn>, the direct supertypes of the parameterized type C<T1,...,Tn> are all of the following:
- C<S1,...,Sn>, where Si contains Ti.
4.5.1. Type Arguments of Parameterized Types:
A type argument T1 is said to contain another type argument T2, written T2 <= T1, if the set of types denoted by T2 is provably a subset of the set of types denoted by T1 under the reflexive and transitive closure of the following rules:
- T <= ? extends T
We therefore know that since ? extends URLClassLoader
contains URLClassLoader
, Class<? extends URLClassLoader>
is a supertype of Class<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:
Class<URLClassLoader> concrete = URLClassLoader.class;
Class<? extends URLClassLoader> wildcard = concrete;
来源:https://stackoverflow.com/questions/24116180/why-cant-assign-i-extends-type-to-type