我正在查看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>
是什么。
答案 0 :(得分:3)
首先,您拥有一个Comparable
界面,大致类似于:
public interface Comparable<T> {
int compareTo(T other);
}
如您所见,Comparable
的类型参数用作compareTo
方法的参数。通常,T
的type参数是与实现Comparable
接口相同的类。这种通用设置有助于将相同类型的实例彼此进行比较。这是一个示例:
public class Name implements Comparable<Name> {
@Override
public int compareTo(Name other) {
// compute & return result
}
}
现在让我们说您有一个方法,该方法应该根据两个对象的自然顺序返回最大值。这种方法如下所示:
public static <U extends Comparable<U>> U max(U left, U right) {
return left.compareTo(right) >= 0 ? left : right;
}
注意:使用U
作为类型变量而不是T
,以表明它与{{1 }}界面。
以上是通用方法。类型变量T
的上限是Comparable
。这意味着,代替U
使用的type参数必须可分配给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
区别在于使用max
作为上限而不是public static <U extends Comparable<? super U>> U max(U left, U right) {
return left.compareTo(right) >= 0 ? left : right;
}
。这两个问答可以帮助解释为什么使用Comparable<? super U>
可以提供更大的灵活性:
答案 1 :(得分:1)
为澄清起见,我们可以将这个令人困惑的表达式分解为元素,然后重新组合在一起。
我们有一个方法find(? array[], ? key)
,它在数组中寻找key
。我们想将此方法用于不同类型的输入参数,例如String
,Integer
等的数组/键。
<U>
我们将<U>
放在方法签名的前面,以表明它是参数方法。这意味着在声明的其余部分,U
是一个占位符,将被调用该方法的类型替换。 (出于以下原因,我将使用U
而不是T
。)
但是,我们不能将U
替换为 any 类型,因为为了能够正确实现该方法,我们希望能够将数组中的元素彼此进行比较(例如,对数组进行排序)。用于定义此行为的常用接口是Comparable。它只有一个方法compareTo
。
<U extends Comparable>
要要求U
类型参数只能用Comparable
的子类型替换(实例化),我们强加 type bound :{{1 }}。这样,我们就可以使用类型安全的方式在extends Comparable
或compareTo
之类的数组元素上调用key
。
但是,我们这里没有做完,因为array[0]
本身是一个通用类型:Comparable
,其中类型参数Comparable<T>
控制{{1}的参数类型}。因此,我们在使用T
时需要实例化compareTo
。
T
在实例化Comparable<T>
中的Comparable<T>
之前,我们的表达式是T
。我们需要将Comparable
替换为所需的类型。 <U extends Comparable<T>>
的参数类型应该是什么?如果我们将T
的数组传递给compareTo
,我们将比较String
,依此类推。在一般情况下,我们将find
的数组传递给{{1 }},因此我们想比较Strings
类型的对象。因此,在这种情况下,我们用另一种通用类型U
:find
在U
中实例化T
,与Comparable<T>
答案 2 :(得分:0)
这意味着T是一个类类型,它是Comparable的子类型或继承该类,并且也接受一个泛型类型,并且它应该与T所表示的类具有相同的类型。
例如
按Employee类和员工类定义替换T如下。
Employee现在是T,并且Comparable的compareTo方法也必须接受Employee作为参数,因为T现在是每个Comparable的Employee。
class Employee implements Comparable<Employee>{
@Override
public int compareTo(Employee o) {
return 0;
}
}