我可以将以下代码转换为使用泛型吗?

时间:2020-03-05 18:52:15  来源:igfitidea点击:

我将一个应用程序转换为使用Java 1.5,并且发现以下方法:

/**
   * Compare two Comparables, treat nulls as -infinity.
   * @param o1
   * @param o2
   * @return -1 if o1<o2, 0 if o1==o2, 1 if o1>o2
   */
  protected static int nullCompare(Comparable o1, Comparable o2) {
    if (o1 == null) {
      if (o2 == null) {
        return 0;
      } else {
        return -1;
      }
    } else if (o2 == null) {
      return 1;
    } else {
      return o1.compareTo(o2);
    }
  }

理想情况下,我想使该方法采用两个相同类型的Comparables,是否可以将其转换以及如何转换?

我认为以下方法可以解决问题:

protected static <T extends Comparable> int nullCompare(T o1, T o2) {

但它未能摆脱IntelliJ中的警告,该警告是"未经检查的对compareTo(T)的调用,它是原始类型'java.lang.Comparable'的成员"。

return o1.compareTo(o2);

解决方案

回答

更改为:

protected static <T extends Comparable<T>> int nullCompare(T o1, T o2) {

我们需要这样做,因为Comparable本身就是一个泛型类型。

回答

这是一个奇怪的情况:

static class A {
    ...
}

static class B extends A implements Comparable<A> {
    public int compareTo(A o) {
        return ...;
    }
}

幸运的是,上面的代码很少见,但是nullCompare()不支持B的比较,除非声明Comparable可以应用于T或者其任何超类:

protected static <T extends Comparable<? super T>> int nullCompare(T o1, T o2) {

即使大多数人永远不会从上述调整中受益,但在为导出的库设计API时,它可能会派上用场。

回答

我不确定泛化此方法是否有意义。目前,该方法适用于任何类型的Comparable;如果我们将其通用化,则必须多次实施(使用完全相同的代码)。有时可以比较两个没有共同祖先的对象,任何通用版本都不允许这样做。

通过添加泛型,我们不会为代码增加任何安全性;在对compareTo的调用中将发生任何安全问题。我建议的只是取消警告。并不是真正警告我们任何有用的东西。

回答

无法编辑,因此我必须发布我的答案。

由于Comparable是泛型的,因此我们需要声明嵌套的类型参数。

protected static <T extends Comparable<? super T>> int nullCompare(T o1, T o2) {

请注意,可比<?超级T>,这使它更加灵活。我们将在Collections.sort上看到相同的方法定义

public static <T extends Comparable<? super T>> void sort(List<T> list) {

回答

为了使其更加通用,我们甚至可以允许它适用于两种不同的类型。 = P

/**
   * Compare two Comparables, treat nulls as -infinity.
   * @param o1
   * @param o2
   * @return -1 if o1&lt;o2, 0 if o1==o2, 1 if o1&gt;o2
   */
  protected static <T> int nullCompare(Comparable<? super T> o1, T o2) {
    if (o1 == null) {
      if (o2 == null) {
        return 0;
      } else {
        return -1;
      }
    } else if (o2 == null) {
      return 1;
    } else {
      return o1.compareTo(o2);
    }
  }