<T extends Comparable<T>> 是什么意思?

What does <T extends Comparable<T>> mean?

我正在查看 java 的 TheAlgorithms 存储库,并首先找到了这个:https://github.com/TheAlgorithms/Java/blob/master/Searches/SearchAlgorithm.java。我看到<T extends Comparable<T>>,但我不知道这是什么意思。我对泛型只知道一点点,我知道语法与参数类型界限有关,但如果有人能澄清这与 Comparable<T> 有什么关系,以及 Comparable<T> 是什么,那就太好了是。

这个论坛上还有一些其他问题类似于我处理实施 <T extends Comparable<T>> 的问题,但答案并没有真正阐明 Comparable<T> 是什么。

It means that T is a class type which is subtype of or inheriting Comparable which also accepts a generic type and it should be of same type as the class which is represented by T here.

例如

将 T 替换为 Employee class 和 Employee class 定义如下。

Employee 现在是 T,Comparable 的 compareTo 方法也必须接受 Employee 作为参数,因为 T 现在是每个 Comparable 的 Employee。

class Employee implements Comparable<Employee>{

    @Override
    public int compareTo(Employee o) {
        return 0;
    }
}

为了澄清,我们可以将这个看起来令人费解的表达式分解成它的元素,然后将它们放回一起。

前提

我们有一个方法 find(? array[], ? key) 可以在数组中查找 key。我们想将此方法用于不同类型的输入参数,例如 StringInteger 的 array/key,等等。

参数类型<U>

我们在方法签名前加上<U>表示它是一个参数化方法。这意味着在声明的其余部分,U 是一个占位符,它将被调用该方法的类型替换。 (我使用 U 而不是 T,原因在下面会变得很明显。)

但是,我们不能将 U 替换为 any 类型,因为为了能够正确实现该方法,我们希望能够比较数组彼此(例如对数组进行排序)。用于定义此行为的通用接口是 Comparable。它只有一个方法,compareTo

类型绑定<U extends Comparable>

为了要求 U 类型参数只能被 Comparable 的子类型替换(可实例化),我们强加了 type boundextends Comparable。这允许我们以类型安全的方式在 keyarray[0] 等数组元素上调用 compareTo

然而,我们到这里还没有完成,因为 Comparable 本身就是一个泛型类型:Comparable<T>,其中类型参数 T 控制 [= 的参数类型20=]。因此,我们需要在使用 Comparable<T> 时实例化 T

实例化Comparable<T>

Comparable中实例化T之前,我们的表达式是<U extends Comparable<T>>。我们需要将 T 替换为所需的类型。 compareTo 的参数类型应该是什么?如果我们将 String 的数组传递给 find,我们将比较 Strings,等等。在一般情况下,我们将 U 的数组传递给 [=41] =],所以我们想比较类型 U 的对象。所以在这种情况下我们在Comparable<T>中用另一个泛型实例化TU<U extends Comparable<U>>,这与<T extends Comparable<T>>

相同

首先,您有 Comparable 界面,大致如下所示:

public interface Comparable<T> {

    int compareTo(T other);
}

可以看到,Comparable的类型参数作为compareTo方法的参数。通常,T 的类型参数与实现 Comparable 接口的 class 相同。这种通用设置有助于将相同类型的实例相互比较。这是一个例子:

public class Name implements Comparable<Name> {

    @Override
    public int compareTo(Name other) {
        // compute & return result
    }
}

现在假设您有一个方法应该return 两个对象的最大值按照它们的自然顺序。这样的方法可能如下所示:

public static <U extends Comparable<U>> U max(U left, U right) {
    return left.compareTo(right) >= 0 ? left : right;
}

注意: 使用 U 作为类型变量而不是 T 以表明它与 [=18= 分开]用于Comparable界面。

以上是通用方法。类型变量 U 的上限为 Comparable<U>。这意味着用于代替 U 的类型参数必须可分配给(即子类型)Comparable<U>。例如,如果我们使用 Name 作为类型参数,它将起作用,因为 Name 可分配给 Comparable<Name>。将上限指定为 Comparable<U> 的原因是该方法需要调用 compareTo 才能正常运行。

Name name1 = ...;
Name name2 = ...;

Name max = max(name1, name2); // U is inferred to be Name

如上所示,将 U 作为 return 类型还允许将结果分配给与参数类型相同的变量。


请注意,为了获得最大的灵活性,max 方法实际上应该这样声明:

public static <U extends Comparable<? super U>> U max(U left, U right) {
    return left.compareTo(right) >= 0 ? left : right;
}

不同之处在于使用 Comparable<? super U> 而不是 Comparable<U> 作为上限。这两个问答应该有助于解释为什么使用 ? super U 提供更大的灵活性:

  • What is PECS (Producer Extends Consumer Super)?
  • Explanation of generic <T extends Comparable<? super T>> in collection.sort/ comparable code?