【问题标题】:Why does the constructor of TreeSet<E> accept the parameter super of E instead of extend of E为什么TreeSet<E>的构造函数接受E的参数super而不是E的extend
【发布时间】:2017-10-22 14:43:14
【问题描述】:

我正在阅读 java 源代码,发现如下:
http://www.java2s.com/Code/JavaAPI/java.util/newTreeSetEComparatorsuperEc.htm

不明白为什么这个构造函数的参数是&lt;? super E&gt;

据我了解,应该是 &lt;? extend E&gt; 而不是 &lt;? super E&gt;,因为如果 E 具有可比性,则 E 的子级必须具有可比性,而 E 的父级可能不具有可比性。

【问题讨论】:

    标签: java comparator


    【解决方案1】:

    让我们考虑三个类:DrinkJuice extends DrinkOrangeJuice extends Juice

    如果我想要TreeSet&lt;Juice&gt;,我需要一个可以比较任意两种果汁的比较器。当然Comparator&lt;Juice&gt; 会这样做。

    Comparator&lt;Drink&gt; 也会这样做,因为它可以比较任意两种饮料,因此也可以比较任意两种果汁。

    Comparator&lt;OrangeJuice&gt; 不会这样做。如果我想在我的果汁集中添加一个AppleJuice,这与此比较器不兼容,因为它只能比较橙汁。

    【讨论】:

      【解决方案2】:

      您创建了一组排序好的香蕉。为此,您需要能够比较香蕉。因此,您可以使用香蕉比较器来做到这一点。但是,如果您有一个可以对任何种类的水果(包括香蕉)进行分类的比较器,那也可以。因此,您也可以使用Comparator&lt;Fruit&gt; 甚至Comparator&lt;Food&gt; 对香蕉进行分类。

      这就是使用Comparator&lt;? super E&gt; 的原因。

      如果是Comparator&lt;? extends E&gt;,您将能够使用Comparator&lt;DriedBanana&gt; 创建一组香蕉。但这行不通:干香蕉的比较器只能比较干香蕉。不是所有种类的香蕉。

      更多信息,另请阅读What is PECS (Producer Extends Consumer Super)?

      【讨论】:

        【解决方案3】:

        它应该是而不是因为如果 E 是 可比的,E 的孩子必须是可比的,而父母 E 可能不是。

        Comparator 不依赖于 Comparable 对象。
        它甚至经常被用作替代品或补充品。

        其实这个构造函数

        public TreeSet(Comparator<? super E> comparator) {...}
        

        本来可以:

        public TreeSet(Comparator<E> comparator) {... }
        

        但是通过指定下界通配符,JDK 开发人员通过允许Comparator 与当前类实例和父类实例互操作,为客户端类提供了更大的灵活性。在某些情况下,这可能是有道理的。

        现在这个:

        public TreeSet(Comparator<? extend E> comparator) {
        

        无效,因为这意味着您可以使用将子类类型指定为参数的compare() 方法结束。
        但是Set 的元素可能包含特定子类的实例,但不仅如此。

        想象一下这段代码:

        TreeSet<CharSequence> set = new TreeSet<>(new Comparator<String>() {
        
            @Override
            public int compare(String o1, String o2) {
                ...
            }
        });
        
        set.add("string");
        set.add(new StringBuilder());
        ...
        

        我想比较Strings,但Set 可以包含String 实例,也可以包含CharSequence 的任何子类,例如StringBuilderCharBuffer 等...
        如果CharSequence 不是abstract,它也可能包含它们的实例。

        通过这个例子,我们明白Comparator&lt;? extend E&gt; 在概念上是错误的。

        【讨论】:

          猜你喜欢
          • 2011-12-22
          • 1970-01-01
          • 2023-01-30
          • 1970-01-01
          • 2011-09-04
          • 1970-01-01
          • 2012-08-22
          • 2020-05-15
          • 2020-10-08
          相关资源
          最近更新 更多