ShapeSaver.class的类型是< ShapeSaver>。当将它提供给genericsHell()时,编译器需要检查Class< ShapeSaver>是Class的子类型扩展ShapeProcessor,这减少到ShapeSaver是否是ShapeProcessor的子类型。子类型关系不成立,方法调用失败。
@波希米亚的解决方案同样如此。这里,在推断T之后,子类型检查发生在T的绑定检查。它也应该失败。这似乎是一个编译器错误,它以某种方式误解了Raw可以分配给Raw< X>的规则。好像Raw是Raw< X>的子类型。另见Enum.valueOf throws a warning for unknown type of class that extends Enum?
一个解决问题的简单方法是声明
void genericsHell(Class extends ShapeProcessor> a)
的确,ShapeSaver是ShapeProcessor的子类型,并且调用编译。
这不只是一个解决方法。有一个很好的理由。严格来说,对于任何类别X,X必须是原始类型。例如,Class< List>可以,Class< List< String>>不是。因为真的没有代表List< string> ;;的类只有一个表示List的类。 不要使用原始类型的严厉警告。有时候我们必须使用原始类型,因为Java类型系统是如何设计的。即使Java的核心API(Object.getClass())也使用原始类型。 你可能打算这样做
genericsHell(ShapeSaver.class);
不幸的是,这是不允许的。 Java可能具有但并没有引入类型文字和泛型。这给很多图书馆带来了很多问题。 java.lang.reflect.Type是一个混乱而不可用的。每个图书馆必须引入自己的类型系统的表示来解决问题。
你可以借一个,例如从Guice,你将能够
genericsHell( new TypeLiteral< ShapeSaver >(){} )
------------------
(在阅读代码时学习跳过ShaveSaver< Circle>周围的骰子)
在genericsHell()的方法体中,您将拥有完整的类型信息,而不仅仅是类。