17

我正在尝试编写一个需要两个Comparables 的通用 max 函数。

到目前为止我有

public static <T extends Comparable<?>> T max(T a, T b) {
    if (a == null) {
        if (b == null) return a;
        else return b;
    }
    if (b == null)
        return a;
    return a.compareTo(b) > 0 ? a : b;
}

这无法编译

The method compareTo(capture#5-of ?) in the type Comparable<capture#5-of ?> is not applicable for the arguments (T)

我认为这是在说?inComparable<?>可能被解释为参数 a 的一种类型,而参数 b 的另一种类型,因此它们无法进行比较。

我怎样才能把自己从这个洞里挖出来?

4

5 回答 5

29

为了获得最佳效果,您应该使用public static <T extends Comparable<? super T>> T max(T a, T b).

问题<T extends Comparable<?>>在于,这表示类型 T 可与某种类型相媲美,但您不知道该类型是什么。当然,常识会规定实现 Comparable 的类至少应该能够与它自己进行比较(即能够与其自己类型的对象进行比较),但从技术上讲,没有什么能阻止类 A 实现Comparable<B>,其中 A和B没有任何关系。<T extends Comparable<T>>解决了这个问题。

但这有一个微妙的问题。假设 X 类实现Comparable<X>了 ,并且我有一个扩展 X 的 Y 类。所以 Y 类Comparable<X>通过继承自动实现。YComparable<Y>类也不能实现,因为一个类不能用不同的类型参数两次实现一个接口。这不是真正的问题,因为 Y 的实例是 X 的实例,所以 Y 可以与 Y 的所有实例相媲美。但问题是您不能在<T extends Comparable<T>> T max(T a, T b)函数中使用类型 Y,因为 Y 没有实现Comparable<Y>. 界线太严了。<T extends Comparable<? super T>>解决了这个问题,因为 T 与 T 的某个超类型(包括所有 T 实例)具有可比性就足够了。回想一下规则 PECS - 生产者extends,消费者super- 在这种情况下,Comparable是一个消费者(它接受一个对象进行比较),所以super是有道理的。

这是 Java 库中所有排序和排序函数使用的类型界限。

于 2011-06-24T10:53:37.153 回答
4

你得到这个错误是因为Comparable<?>基本上说它可以与没有任何细节的东西相提并论。您应该Comparable<T>改为编写,这样编译器就会知道类型 T 与自身具有可比性。

于 2011-06-23T10:05:52.043 回答
1

从 SO 生成的相关链接中回答我自己的问题 - 这似乎是Fun with Java generics的微妙重复,尽管我想你不能怪我没有找到它的标题!

最简单的解决方案似乎是

public static <T extends Comparable<T>> T max(T a, T b) {
    if (a == null) {
        if (b == null) return a;
        else return b;
    }
    if (b == null)
        return a;
    return a.compareTo(b) > 0 ? a : b;
}
于 2011-06-23T10:08:45.313 回答
1

我为此编写了一个实用程序类。也许您觉得它很有用(该库是开源的):

http://softsmithy.sourceforge.net/lib/docs/api/org/softsmithy/lib/util/Comparables.html

主页:

http://www.softsmithy.org

下载:

http://sourceforge.net/projects/softsmithy/files/softsmithy/

马文:

<dependency>  
    <groupid>org.softsmithy.lib</groupid>  
    <artifactid>lib-core</artifactid>  
    <version>0.1</version>  
</dependency> 
于 2011-06-23T10:10:32.233 回答
1

最好是已经实现了iso create owns。请参阅具有两个 Comparable 的 Min/Max 函数。最简单的是org.apache.commons.lang.ObjectUtils

Comparable<C> a = ...;
Comparable<C> b = ...;
Comparable<C> min = ObjectUtils.min(a, b);
于 2019-05-05T18:10:33.770 回答