【发布时间】:2018-05-15 18:56:41
【问题描述】:
我正在用 Java 实现一个使用泛型的库。据我了解,Java 后期引入了泛型类型,以提供类似于 C++ 中模板的功能,同时也保持向后兼容性。话虽如此,运行时的参数化类型AVLTree<K, V> 只是显示为
AVLTree,因此得名“类型擦除”。
我发现以下三种编写类定义的方法是等效的,因为编译器不会抱怨,也不会遇到与类型相关的任何奇怪的运行时问题。我没有使用反射,所以我没有看到这方面的好处。
有人告诉我不要使用这个:
AVLTree<K extends Comparable<K>, V>
相反,他们说,使用这个:
AVLTree<K extends Object & Comparable<? super K>, V>
但是,以下也可以:
AVLTree<K extends Comparable<? super K>, V>
我已经读过,如果您可以避免使用 SomeClass<E>,那么您应该避免使用这种语法,并且较新的 Java 正在使用这种语法 <?>. 有人可以澄清一下这对我的代码的区别和影响吗?如果我不一致,我是否可能会引入错误?
【问题讨论】:
-
我会说
K extends Comparable<? super K>是正确的。Object是不必要的和暗示的(总是)。Comaparble<X>实际上不会为某些类编译(如果Comparable实际上是在X的超类上实现的)。但除此之外,您的问题非常广泛,可能应该分解成更小、更集中的问题。 -
据我了解,某些方法(例如
Collections.max())具有额外的Object &绑定的原因是因为(在Collections.max()的情况下)这是此的预泛型版本方法有返回类型Object,并且他们需要方法的泛型版本具有相同的运行时签名,因此他们需要将T擦除为Object而不是Comparable。添加额外的Object绑定首先会导致擦除为Object而不是Comparable。可以说,pre-generics 版本应该返回Comparable,但他们没有,所以他们坚持这样做。 -
但除非您担心签名与您的库的先前版本的兼容性,或者类似的东西,否则我看不出您有任何理由添加多余的
Object &绑定。 -
@newacct 这是一个很好的观点。考虑到这一点,我将省略它,因为我正在使用绝对需要擦除可比较的对象 - 例如 AVLTree、RedBlackTree,我需要在其中对值进行排序。谢谢
标签: java templates generics types