【问题标题】:Is there a difference between these two generic signatures of a "max" function for a collection集合的“max”函数的这两个通用签名之间是否有区别
【发布时间】:2017-03-25 14:43:17
【问题描述】:

这两个签名有实际区别吗:

public static <T extends Comparable<? super T>> T max(Collection<T> c) 

public static <T extends Comparable<T>> T max(Collection<? extends T> c) 

我想不出这两个不能互换的单一用例。

那么两者兼有的原因是什么?超级T和?在 Java 集合中的标准 max() 方法中扩展 T:

public static <T extends Comparable<? super T>> T max(Collection<? extends T> coll)

编辑: 这个问题不是关于&lt;? super T&gt;&lt;? extends T&gt; 之间的区别。 get/put 原则对我来说很清楚。 问题在于这两个特定签名之间的区别以及为什么 Java Collections API 的创建者决定为他们的标准“max”函数创建这两个签名的混合体。

【问题讨论】:

标签: java generics


【解决方案1】:

两者不可互换的例子是:

static class A implements Comparable<Object> {
    @Override
    public int compareTo(final Object o) {
        return 0;
    }
}

包含A 实例的列表适用于第一个max(),而第二个max() 则失败:

error: method max2 in class Generics cannot be applied to given types;
    max2(Arrays.asList(new A()));
    ^
required: Collection<? extends T>
found: List<A>
reason: inference variable T has incompatible bounds
  equality constraints: Object
  upper bounds: Comparable<T>
where T is a type-variable:
  T extends Comparable<T> declared in method <T>max2(Collection<? extends T>)

另一个例子:

static class A {}
static class B extends A implements Comparable<A>{
    @Override
    public int compareTo(final A o) {
        return 0;
    }
}

max() 以这种方式设计以确保其签名不会更改,并且所有依赖于max()(Java 5 之前的代码)返回Object 的编译代码仍然可以工作,@987654321 中的更多详细信息@。

【讨论】:

  • 是的,正确的。似乎这两个签名不像我想象的那样可以互换。谢谢!
【解决方案2】:

举个简单的例子

动物:

class Animal extends Mammal

猫:

class Cat extends Animal

让我们分解签名。

max(Collection<? extends T> coll)

这是因为 max 应该接受 Animal 和 Cat 的列表。 现在,剩下的部分:

<T extends Comparable<? super T>>

这涵盖了我的 Animal 类签名如下的情况:

Animal extends Mammal implements Comparable<Mammal>

所以,我的可比较对象可以接受它的任何父母,并且仍然进行逻辑比较。我知道这不是一个非常实际的例子,但我希望它有意义。

【讨论】:

    【解决方案3】:

    那么两者兼有的原因是什么?超级T和?在 Java 集合中的标准 max() 方法中扩展 T:

    只是提供一个尽可能通用的最大操作,因为它将对该集合及其元素执行的操作只是iterator().nextcompareTo。换句话说,它声明了其参数类型所需的最弱约束,仍然允许其代码编译。

    【讨论】:

    • 签名的公共静态 > T max(Collection extends T> c) 变体正是提供了这一点。所以在某种程度上我可以理解为什么第二个变体可以被认为比第一个更好。但我仍然没有看到混合的正当理由。
    • 目前我在我的移动设备上,所以现在很难详细查看它......但是一个无脑的测试是提取这些方法的代码并使用签名,看看为什么这些变化会导致编译问题。
    猜你喜欢
    • 2017-12-04
    • 2017-10-20
    • 2018-11-01
    • 2015-12-26
    • 2023-01-28
    • 2011-12-28
    • 2014-03-17
    • 1970-01-01
    • 2012-08-06
    相关资源
    最近更新 更多