“参数类型兼容性”(无论如何称呼它)背后的一般原理是什么?
Class<Base> cls1 = new Derived().getClass(); // ERR
Class<? extends Base> cls2 = new Derived().getClass(); // OK
Class<? super Base> cl3 = new Derived().getClass(); // ERR
Class<Base> cls4 = new Base().getClass(); // ERR
Class<? extends Base> cls5 = new Base().getClass(); // OK
Class<? super Base> cls6 = new Base().getClass(); // ERR
我的答案
: LHS中的 Class<Base> cls1
正确地期望 Class<Base>
在RHS中=> Class<? extends Derived>
是错误的。
Class<? extends Base> cls2
表示,从cls2(通过迭代器或(假设存在)“获取”方法)获得的任何内容都是Base(因此我们可以在我们得到了什么)。 Class<? extends Derived>
在任何情况下均为Base(无论是Derived还是其子类)。这样就可以编译。
Class<? super Base> cls3
意味着我们总是可以通过“假设存在”“添加/放入”方法将Base添加到cls3中-因此Collection包含Base或其超类。 Class<? extends Derived>
永远不会是Base =>错误。
我了解到new Derived().getClass()
返回Class<? extends Derived>
,同样new Base().getClass()
返回Class<? extends Base>
。
我知道List<? extends String> lst = new ArrayList<String>();
还可以,为什么。
我了解数组协方差和协方差返回类型。
但是上述测试问题使我不胜其烦-我无法制定规则以指导我的推理。
P.S。 PECS的回答对我没有帮助,因为主要是他们以“我可以添加或放入集合/对象还是同时放入集合/对象”的角度来看问题。我的问题的重点是引用兼容性。
答案 0 :(得分:4)
给出类型为expression.getClass()
的表达式,Class<? extends T>
返回expression
,因为T
是T
或Class<? extends |T|>
的子类。 (严格来说,它是一个||
,其中T
表示擦除;但这在此问题的上下文中是不必要的细节,其中expression.getClass()
的值都不是通用的。)
鉴于这一事实,Class<T>
既不是Class<? super T>
也不是List<? extends Number>
,就像List<Number>
不是List<? super Number>
或{{ 1}}。
something
是否为new SpecificSomething()
并不重要:那不是Class<SpecificSomething>
,因为事实是它是一个新实例(并且保证它确实是一个{{1} })不被考虑:SpecificSomething
是类型new SpecificSomething()
的表达式,因此SpecificSomething
返回getClass()
。