【问题标题】:The correct signature of a utility function to Array class: Comparable<E> or Comparable<? super E>?实用函数对 Array 类的正确签名:Comparable<E> 或 Comparable<?超级E>?
【发布时间】:2020-01-09 05:10:15
【问题描述】:

我正在尝试将实用程序函数写入 Array 类。

该函数应返回所有可比类型的最小元素。

我的问题是该函数应该具有哪个签名:

  1. public static &lt;E&gt; E min (Comparable**&lt;E&gt;**[] arr)
  2. public static &lt;E&gt; E min (Comparable**&lt;? super E&gt;**[] arr)

在 Java 中,数组是变体,这意味着如果 B 扩展 A,那么 A[] 和 B[] 也是相关的,但 ArrayList&lt;A&gt;ArrayList&lt;B&gt; 没有相同的连接。

这是完整的代码:

@SuppressWarnings("unchecked")
public static <E> E min (Comparable<E>[] arr){

    E min= null;

    if(arr.length > 0)          
        min = (E) arr[0];

    for (int i = 1; i < arr.length; i++) {

        if( (arr[i].compareTo((E) min)) < 0)
            min = (E) arr[i];
    }

    return min; 
}

评论:我有两个类 A 实现 Comparable AB 扩展 A

当签名为 Comparable&lt;? super E&gt; 时,调用(来自 main)到:

A aArr[] = new A[] {new A(1), new B(2), new B(-1)};
B bb = min(aArr);

是一个编译错误:cannoot convert from ...A to ... B,但是当 min() 的签名是 Comparable&lt;? super E&gt; 时,同样的调用就可以了。

谢谢

【问题讨论】:

  • 如果您的问题已关闭,您可以接受答案。或者让我们知道,如果您仍在寻找解决方案或澄清

标签: java comparable type-bounds


【解决方案1】:

第二个签名有效,因为 A 是 B 类的超类,而它适合通配符条件? super B

如果您希望您的函数返回 any 可比较类型数组的最小值,您只需要。

public static <E extends Comparable<E>> min (E[] arr)

这将允许您使用该方法来操作所有类型的数组,其值具有可比较的类型。在您的情况下,您希望 A 和 B 相关。因此,您还应该允许您的方法采用 E 类及其超类的参数。但是,仅当您尝试将 A 转换为 B 时,才需要它,如您的示例所示。这使您希望您的方法采用 E 的超类(因为 A 是 B 的超类)并且仍然返回 E 类型的值。

public static <E extends Comparable<? super E>> min (E[] arr)

【讨论】:

  • 但再次调用:'B bb = min(aArr);'得到同样的错误...,但是 >工作正常
  • @HodiyaEyal 我猜是问题所在,你不能让 B 变量持有对 A 类型对象的引用,因为 A 不一定是 B 的实例,让我考虑一下
  • @HodiyaEyal 我编辑了我的答案。所以是的,在你的情况下,你还应该照顾超级类型。请注意,在相反的情况下,代码将不起作用,因此对于A=min(arrB),您应该使用? extends E。这取决于您选择使用的层次结构和类关系
【解决方案2】:

这两个签名都不是此方法的“正确”签名,IMO。正确的签名是接受E[],其中E extends Comparable&lt;? super E&gt;

public static <E extends Comparable<? super E>> E min (E[] arr){

    E min= null;

    if(arr.length > 0)
        min = arr[0];

    for (int i = 1; i < arr.length; i++) {

        if( (arr[i].compareTo(min)) < 0)
            min = arr[i];
    }

    return min;
}

您当前的实现错误地假设“实现Comparable&lt;T&gt; 的类必须是TT 的子类”。这不一定是真的。这就是为什么你必须禁止这些警告。

无论如何,回到你的实际问题。在调用方,您正在执行B bb = min(aArr)。在Comparable&lt;E&gt; 的情况下,出现错误是因为编译器无法推断出E 应该是什么。它不能是A,因为A 不能分配给B 类型的变量。它也不能是B,因为你给它的是A[],它不是Comparable&lt;B&gt;[]

当您将其更改为 Comparable&lt;? super E&gt; 时,E 可以现在是 B。由于A[]Comparable&lt;? super B&gt; 兼容。

但这只能以真正“hacky”的方式工作,因为从技术上讲,您将数组中的每个元素都转换为B,因为EB,并且由于Java 泛型被擦除的方式,这不会失败。

您的问题的根源确实在于B bb = min(aArr) 行。您可能错误地假设aArr 的最小值是B 类型。你为什么这么肯定?也可以是A,对吧?使用我上面的解决方案,如果您确定结果是B,则需要将结果转换为B

B bb = (B)min(aArr);

【讨论】:

    猜你喜欢
    • 2011-10-31
    • 2014-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-05
    • 1970-01-01
    相关资源
    最近更新 更多