2011-06-23 14 views
14

私は2つのComparableを取る一般的なmax関数を書こうとしています。Javaで汎用の `max(Comparable a、Comparable b)`関数を実装する方法は?

これまでのところ、私はこれは私がこれを言っていると思う何

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

でコンパイルに失敗し

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

を持っているがComparable<?>?はパラメータaのための一つのタイプとして解釈することができるということで、パラメータbのためにもう1つは比較できないようにします。

どうすればこの穴から自分を掘り出すことができますか?

+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#)をご覧ください。 –

答えて

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は異なるタイプのパラメータでインターフェイスを2回実装できないため、Comparable<Y>も実装できません。 YのインスタンスはXのインスタンスなので、これは実際問題ではないので、YはYのすべてのインスタンスに匹敵します。しかし、YはComparable<Y>を実装していないため、<T extends Comparable<T>> T max(T a, T b)関数でタイプ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

クール、ありがとうございます。これは、標準ライブラリの一部ではなく、間違ったコードがどれほどか、どれほど簡単であるかを考えれば、私がうまくいかないものです。 –

+0

注:私はソースコードをチェックしました。現在はnull値をサポートしていません: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

:-)きれいに来てくれてありがとうございます - 私は確信していますが、私は多くの日付がなかったドメインを扱っていなかったでしょう供給される。 –

関連する問題