这是一个声明
public class BinarySearchTree<AnyType extends Comparable<? super AnyType>> {
....
}
这是另一个宣言
public class BinarySearchTree<AnyType extends Comparable<AnyType>>{
.....
}
我知道第一个声明是首选(在很多java示例和教科书中看到它),但为什么会这样?当我尝试使用第二个声明时,我的所有代码都运行良好。
我知道在这种情况下超级使用了吗? super AnyType,表示AnyType或其任何超类。 Super
对我来说,两个人都说这个类BinarySearchTree支持任何可比较的对象类型。任何人都可以描述或举例说明这种微妙的差异实际上会产生什么影响吗?
以狗为例
class Animal implements Comparable<Animal>
class Dog extends Animal
public class BinarySearchTree<AnyType extends Comparable<? super AnyType>> {
...}
Would allow for
BinarySearchTree<Dog> but
public class BinarySearchTree<AnyType extends Comparable<AnyType>>{
.....
} wouldn't
答案 0 :(得分:3)
任何人都可以描述或举例说明这种微妙的差异实际上会产生什么影响吗?
是。 JDK的两个例子:
你会注意到后者扩展了前者,但{s} Date
实现的是Comparable
的{{1}}。
如果它“仅”实施java.util.Date
,那么您将无法将其与“正常”Comparable
进行比较。
还要考虑Date
的简单情况(Java 8中出现的界面)。最常用的Consumer
是Consumer
;在这种情况下,它的参数是System.out::println
。
现在,如果Object
Stream
的签名是.forEach()
而不是.forEach(Consumer<T> consumer)
,那么您根本无法使用“普遍消费者” ,除了.forEach(Consumer<? super T>)
s!
这是PECS规则的CS部分(Producer Extends,Consumer Super)。
答案 1 :(得分:2)
如果你有
class Animal implements Comparable<Animal>
class Dog extends Animal
然后BinarySearchTree<Dog>
与第一个签名合法,但与第二个签名不合法。第二个签名不合法,因为Dog
没有实现Comparable<Dog>
(并且没有办法让它实现Comparable<Dog>
,因为它已经实现了Comparable<Animal>
和一个类型无法实现具有两个不同类型参数的接口。)
如果您考虑一下,BinarySearchTree<Dog>
完全正常,因为Dog
与自己相当(实际上它们与所有Animal
相当,其中包括所有Dog
} S)。我们所需要的只是保证someDog.compareTo(someOtherDog)
有效。为了实现这一点,我们不需要compareTo
完全采用Dog
- Dog
的任何超类型也可以。这就是? super
所代表的含义。它放松了对更一般的约束,仍然提供我们需要的所有类型保证。在泛型中,我们应该始终使用限制性最小的界限来为我们提供所需的类型安全性。
另一种思考方式是通过PECS规则(Producer extends
,Consumer super
)。 Comparable<T>
只能是T
的“使用者”,因为其唯一方法采用T
类型的参数,并且不会返回T
。因此,Comparable
应始终与? super ...
通配符一起使用。