Why can't assign I <? extends Type> to ?

后端 未结 2 1122
半阙折子戏
半阙折子戏 2020-12-11 18:22

The following statements:

URLClassLoader ucl = (URLClassLoader) ClassLoader.getSystemClassLoader();
Class uclc = ucl.getClass();


        
相关标签:
2条回答
  • 2020-12-11 18:39

    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;
    
    0 讨论(0)
  • 2020-12-11 18:40

    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.

    0 讨论(0)
提交回复
热议问题