关于泛型,有界通配符和getClass()的棘手面试问题

时间:2019-08-09 17:57:38

标签: java generics

“参数类型兼容性”(无论如何称呼它)背后的一般原理是什么?

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>是错误的。

根据 PECS

Class<? extends Base> cls2表示,从cls2(通过迭代器或(假设存在)“获取”方法)获得的任何内容都是Base(因此我们可以在我们得到了什么)。 Class<? extends Derived>在任何情况下均为Base(无论是Derived还是其子类)。这样就可以编译。

根据 PECS

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的回答对我没有帮助,因为主要是他们以“我可以添加或放入集合/对象还是同时放入集合/对象”的角度来看问题。我的问题的重点是引用兼容性。

1 个答案:

答案 0 :(得分:4)

给出类型为expression.getClass()的表达式,Class<? extends T>返回expression,因为TTClass<? 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()