0

という事は承知しています

List<? extends T>

リストが T (または T 自体) の任意のサブタイプであることを許可し、

List<T>

タイプ T のリストのみを許可します。ただし、次のメソッド シグネチャを見てください。

public static <T extends Object & Comparable<? super T>> T findMax(List<? extends T> myList, int begin, int end){

そして、次のクラス:

public class ClassA{

}
public class ClassB extends ClassA implements Comparable<ClassA>{
public int compareTo(ClassA s){
    //do comparison
}
}
public class ClassC extends ClassB{

}

T が ClassB で、リストに T のサブタイプ (ClassC) を渡したいとします。

public static void main(String[] args){
    List<ClassC> myC = new ArrayList<ClassC>();
    ClassC a = findMax(myC, 2, 3);
}

この場合、Java は T が ClassC ではなく ClassB であることをどのように推測しますか? また、ClassB を推論できない場合 (実際には ClassC を推論する場合)、次のメソッド シグネチャ ("List" なし) は同等ではないでしょうか?

public static <T extends Object & Comparable<? super T>> T findMax(List<T> myList, int begin, int end){

ありがとう、ジャック

4

3 に答える 3

5

まず、すべて? extends Objectがオブジェクトを拡張するため、値を追加しないため、これら 2 つのメソッドは同等です。

public static <T extends Object & Comparable<? super T>> T findMax(List<T> myList, int begin, int end)
public static <T extends Comparable<? super T>> T findMax(List<T> myList, int begin, int end)

その単純化を行った後、あなたの質問は基本的にこれらと同等です:

public static <T extends Comparable<? super T>> T findMax(List<T> myList, int begin, int end)
public static <T extends Comparable<? super T>> T findMax(List<? extends T> myList, int begin, int end)

それらは (同じではない*.

その理由は、2 番目のメソッドでは、返される型のサブクラスである型を持つ List を渡すことができるのに対し、最初のメソッドでは、List の型は返される型と同じ型でなければならないからです。

于 2012-08-25T13:27:40.833 に答える
0

型推論が機能する方法Tは、関数を呼び出すリストの型パラメーターに常に推論されるため、によって与えられる追加の自由<? extends T>は決して使用されません。List<T>同じ結果で書き込むことができます。

ボヘミアンによって提起されたより微妙な点に答えると、推論された型は任意のスーパータイプにも割り当てられるため、署名が長くなっても柔軟性が追加されません。

于 2012-08-25T13:26:51.617 に答える
0

javaは、TがClassCではなくClassBであることをどのように推測しますか?

ここではフォローしません。Generics はコンパイル型の手法です。
の消去public static <T extends Object & Comparable<? super T>> T findMax(List<? extends T> myList, int begin, int end)は次のようになります。Objectつまり
、これは次のようにコンパイルされます。public static Object findMax(List myList, int begin, int end)

リストをインスタンス化List<ClassC> myC = new ArrayList<ClassC>();してメソッドに渡すと、コンパイラは型の安全性を保証します。つまり、渡すリストが宣言に準拠しているということです。この場合Class C、 a を実装し、コンパイラがそれを受け入れるため、Comparable元に戻すことができます。 ジェネリックは実行時には存在しません。 Class B

コメント後の更新:
これpublic static <T extends Object & Comparable<? super T>> T findMax(List<? extends T> myList, int begin, int end)

次と同じではありません:

public static <T extends Object & Comparable<? super T>> T findMax(List<T> myList, int begin, int end)

これは型推論に関するものではありません。コンパイラは、ここで同じ型推論を行うT? extends T、この特定のケースで行います。
違いは契約にあります。は、コレクションを変更しないことを保証public static <T extends Object & Comparable<? super T>> T findMax(List<? extends T> myList, int begin, int end) するメソッドを宣言します (少なくともコレクションを破損する方法ではありません)。 は基本的に list を読み取り専用リストにし、その本体内ではを除くリスト (またはサブタイプのいずれか)にインスタンスを追加できません。 宣言した場合、それは読み取り専用リストではなく、リストに要素を追加できます。たとえば、内部で次のことができます。asの宣言ではこれは不可能です。
List<? extends T> myListfindMaxTTnull
List<T> myListfindMaxmyList.add(myList.get(0));findMaxList<? extends T> myList

于 2012-08-25T13:35:32.383 に答える