2016-03-01 19 views
23

はなぜCollections.sort(List<T>)は、署名を持っていない理由Collections.sort()の宣言:</p> <pre><code>public static <T extends Comparable<? super T>> void sort(List<T> list) </code></pre> <p>及びません:<? super T>ではなく<T>

public static <T extends Comparable<T>> void sort(List<? extends T> list) 
  • 私は彼らの両方が同じに役立つであろうことを理解目的;なぜフレームワーク開発者は最初のオプションを使用しましたか?
  • これらの宣言は本当に異なっていますか?

答えて

19

あなたの提案された署名はJava-8でおそらく動作します。しかし、以前のJavaバージョンでは、型推論はそれほど賢明ではありませんでした。 List<java.sql.Date>があるとします。 java.sql.Datejava.util.Dateを拡張し、Comparable<java.util.Date>を実装することに注意してください。コンパイル時

List<java.sql.Date> list = new ArrayList<>(); 
Collections.sort(list); 

これはJava 7で完全に機能します。ここでTjava.sql.Dateと推定され、実際にはComparable<java.util.Date>であり、Comparable<? super java.sql.Date>であると推定されます。しかしのはあなたの署名を試してみましょう:

public static <T extends Comparable<T>> void sort(List<? extends T> list) {} 

List<java.sql.Date> list = new ArrayList<>(); 
sort(list); 

ここTjava.util.Dateと推測されるべきです。しかし、Java 7の仕様ではこのような推論ができません。したがって、このコードは、Java 8でコンパイルが、Java-7でコンパイルするとき失敗することができる。

Main.java:14: error: method sort in class Main cannot be applied to given types; 
     sort(list); 
     ^
    required: List<? extends T> 
    found: List<Date> 
    reason: inferred type does not conform to declared bound(s) 
    inferred: Date 
    bound(s): Comparable<Date> 
    where T is a type-variable: 
    T extends Comparable<T> declared in method <T>sort(List<? extends T>) 
1 error 

型推論を大幅ジャワ-8に向上しました。別のJLS chapter 18がこれに専念していますが、Java-7ではルールがより簡単です。were彼らはタイプTTの定義におけるComparableへの型引数との関係に異なる要件を課しているため

+1

しかし、static > T max(Collection c)はうまくいきます...これは再び推論の問題ですか? – prvn

+0

@prvnの場合、提案されている署名のように 'Comparable 'の代わりに' Comparable 'があります。 '> void sort(List list)'も使えますが、 '? extends T'はここでは完全に不要で、 'max'メソッドでは合理的です(' max'は値を​​返します)。 –

+6

もう一つのポイントがあります。 'List list'のようなワイルドカード型の場合、メソッド内で' list.set(index、list.get(anotherIndex)) 'を実行することはできません。これは内部ヘルパーメソッドで '? Tを他の型変数に拡張します(あるいは、内部実装がしばしば行うようにチェックされていない操作を使用することによって)が、ワイルドカードを持たない型は、変更されるリストに対してよりクリーンです。 – Holger

4

? super TTよりも制限が少ないため、これらは異なります。それはあるLower Bounded Wildcard(リンクJavaチュートリアルは、部分的に、と言う)前者は唯一のタイプIntegerのリストと一致するため、後者は任意の型のリストと一致したのに対し、

用語List<Integer>が、List<? super Integer>よりも制限さスーパータイプはIntegerです。

TIntegerを交換し、それがTまたはjava.lang.Objectを意味します。

+0

しかし、私はsort()の議論で柔軟性を高めています。使用していますか? – prvn

+0

はい、誰も 'List <?スーパー整数>は 'List 'と同じです。 2番目のバージョンは 'extends'を使います。これが同じであれば問題になります。 – JojOatXGME

+0

私はあなたの答えは直接質問に関連しているとは思わない。 – yuxh

9
// 0 
public static <T extends Comparable<? super T>> void sort0(List<T> list) 

// 1 
public static <T extends Comparable<T>> void sort1(List<? extends T> list) 

これらの署名が異なります。

あなたはこのクラスを持っていること、たとえば仮定:あなたは

List<A> list = ... ; 
sort0(list); // works 
sort1(list); // fails 

を持っている場合

class A implements Comparable<Object> { ... } 

はその後sort1が失敗した理由は、それ自体に匹敵両方でタイプTがないことですリストの型のスーパータイプ、またはそのスーパータイプです。

のオブジェクトは、Comparableのオブジェクトが特定の要件を満たす必要があるため、不正な形式になっています。特に、比較を逆にすると、結果の符号が反転するはずです。 AのインスタンスをObjectと比較することはできますが、その逆はできません。したがって、この要件は違反されます。しかし、これはセマンティクスの要件であり、Comparableであり、タイプシステムによって課されないことに注意してください。型システムだけを考慮すると、2つの宣言は実際には異なります。

関連する問題