2011-06-23 65 views
14

我想写一个通用的最大功能,需要两个Comparable s。如何在Java中实现泛型`max(Comparable a,Comparable b)`函数?

到目前为止,我有

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) 

来编译,我认为这是什么意思是说,在Comparable<?>?可以被解释为一种类型的参数,另一个用于参数b,以便它们不能被比较。

我该如何挖掘出这个洞?

+0

在'if(a == null)'块中,不需要嵌套if子句。将块减少到'return b;'产生相同的结果(当'b'为'null'时为'null',否则为'b')。 – benjamin

+0

请参阅[org.apache.commons.lang3.ObjectUtils.compare](https://commons.apache.org/proper/commons-lang/javadocs/api-3.6/org/apache/commons/lang3/ObjectUtils.html#比较 - TT-) –

回答

24

为获得最佳效果,您应该使用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>。 Y类不能实现Comparable<Y>,因为类不能使用不同的类型参数实现两次接口。这并不是一个问题,因为Y的实例是X的实例,所以Y可以与Y的所有实例相比较。但问题是,不能使用类型Y与您的<T extends Comparable<T>> T max(T a, T b)函数,因为Y没有实现Comparable<Y>。边界太严格了。<T extends Comparable<? super T>>解决了这个问题,因为T足以与T的某个超类型(其中包含所有T实例)相媲美。回想一下规则PECS - 制造商extends,消费者super - 在这种情况下,Comparable是一个消费者(它需要一个对象进行比较),因此super是有意义的。

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

4

你会得到这个错误,因为Comparable<?>基本上说它可以媲美没有任何细节的东西。您应该编写Comparable<T>,以便编译器知道类型T与其自身相当。

+0

谢谢 - 现在解决真正的问题,这是它将其移植到Scala! –

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; 
} 
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/

Maven的:

<dependency> 
    <groupid>org.softsmithy.lib</groupid> 
    <artifactid>lib-core</artifactid> 
    <version>0.1</version> 
</dependency> 
+0

很酷,谢谢。这是我gobsmacked不是标准库的一部分,考虑到需要多少代码,以及如何容易出错。 –

+0

注意:我刚刚检查了源代码:它目前不支持空值:http://softsmithy.hg.sourceforge.net/hgweb/softsmithy/lib/main-golden/file/5c4db802573b/lib-core/src /main/java/org/softsmithy/lib/util/Comparables.java – Puce

+0

:-)感谢您的干净 - 我确信我的地址本不会有我没有处理的地区很多日期可能不会提供。 –

相关问题