为什么 Java PriorityQueue 实现使用 Comparator<? super E> 而不是简单的 Comparator<E>
Why does the Java PriorityQueue implementation use Comparator<? super E> and not simply Comparator<E>
jdk8中定义的JavaPriorityQueue源码使用了这样定义的比较器
/**
* The comparator, or null if priority queue uses elements'
* natural ordering.
*/
private final Comparator<? super E> comparator;
源代码here(第 108 行)
为什么需要使用 E 的超类型而不是简单的 E。
换句话说,为什么不像下面这样定义比较器:
private final Comparator<E> comparator;
额外抽象背后的动机是什么?
因为为什么不。
给定一个可以比较任何 2 个 CharSequence 对象的比较器(CharSequence 是一个接口;String、StringBuilder 和其他一些实现它的东西),然后..当你只需要比较时,这同样好字符串。所有的字符串也是 CharSequences,所以一个比较器可以告诉你对于任何 2 个字符序列对象,哪个 'comes first' 可以完美地完成这项工作。
泛型在默认情况下是不变的,所以如果你有一个 PriorityQueue<String>
,并且它像你想要的那样工作,它看起来像 Comparator<E>
,这意味着 Comparator<String>
,并且Comparator<CharSequence>
不兼容。就像将 String
传递给需要 Integer
对象的方法一样,它不会编译。
因此,<? super E>
这样您 就可以 传递一个 Comparator<CharSequence>
。
当然,它不常出现,但 'more correct' 是这样的。我敢肯定,如果您碰巧有一个 CharSequences 的比较器,但不能用它来为 PriorityQueue<String>
.
供电,您一定会感到惊讶。
jdk8中定义的JavaPriorityQueue源码使用了这样定义的比较器
/**
* The comparator, or null if priority queue uses elements'
* natural ordering.
*/
private final Comparator<? super E> comparator;
源代码here(第 108 行)
为什么需要使用 E 的超类型而不是简单的 E。
换句话说,为什么不像下面这样定义比较器:
private final Comparator<E> comparator;
额外抽象背后的动机是什么?
因为为什么不。
给定一个可以比较任何 2 个 CharSequence 对象的比较器(CharSequence 是一个接口;String、StringBuilder 和其他一些实现它的东西),然后..当你只需要比较时,这同样好字符串。所有的字符串也是 CharSequences,所以一个比较器可以告诉你对于任何 2 个字符序列对象,哪个 'comes first' 可以完美地完成这项工作。
泛型在默认情况下是不变的,所以如果你有一个 PriorityQueue<String>
,并且它像你想要的那样工作,它看起来像 Comparator<E>
,这意味着 Comparator<String>
,并且Comparator<CharSequence>
不兼容。就像将 String
传递给需要 Integer
对象的方法一样,它不会编译。
因此,<? super E>
这样您 就可以 传递一个 Comparator<CharSequence>
。
当然,它不常出现,但 'more correct' 是这样的。我敢肯定,如果您碰巧有一个 CharSequences 的比较器,但不能用它来为 PriorityQueue<String>
.