ホームページ >Java >&#&チュートリアル >Java ジェネリックスの共分散、反分散、拡張および超選択メソッド
共分散と反分散を理解するには、まず次のことを導入する必要があります。
リスコフ置換原理によれば、C が P のサブクラスである場合、P は C を置き換えることができます。つまり、 P p = new C();
C は P から継承し、 C
F が不変の場合、 C
たとえば、リスコフ置換原則によれば、Integer は Number のサブクラスです。
Number number = new Integer(1); //correct
ただし、このように書くとエラーが報告されます
List<Number> list = new ArrayList<Integer>(1); //error
Number と Integer には Integer b990d0161a5780c8b48560ac36663132 および Listc0f559cc8d56b43654fcbe4aa9df7b4a
と見なされます。継承関係はありません
F が共分散の場合, when C
Java は、不変性を共分散に変換するための extends を提供します。次に例を示します。 ##List<? extends Number> list = new ArrayList<Integer>(1); //corrent
このとき、
は、ArrayListc0f559cc8d56b43654fcbe4aa9df7b4a
Number の特定のサブクラスを表す型範囲として見ることができます配列はデフォルトで共変です
Number[] numbers = new Integer[3];
反変性とは
If F は反変です。C = F(P)Java は、不変式を共変式の Change に変換するためのスーパーを提供します。 :
List<? super Number> list = new ArrayList<Object>(1); //corrent
このとき、
は、ArrayLista87fdacec66f0909fc0757c19f2d2b1d
## の親クラスとみなすことができます。 #extends と super
public interface List<E> extends Collection<E> { boolean add(E e); }次のコードはエラーを報告しますか?
? extends Number は Integer 型
List<? extends Number> list = new ArrayList<Integer>(); // correct list.add(Integer.valueOf(1)); //error
と一致しません。まず、add メソッドが呼び出されるとき、汎用の
E自動的に a2b037db85f4e1df0e812b9647ac55a8 2 行目はエラーを報告します。これは、
? extends Number
Integer## の親クラスではないことを意味します。 #。ここで、Lista2b037db85f4e1df0e812b9647ac55a8
が ArrayListc0f559cc8d56b43654fcbe4aa9df7b4a
の親クラスであることを区別する必要があります。 ? extends Number
は、Number の特定のサブクラスを表す、型範囲内の特定の型と見なすことができますが、それがどのサブクラスであるかは明確ではありません。Float または Short である可能性があります。 . 、または Integer のサブクラスである可能性があります (Integer は Final によって変更され、サブクラスを持つことはできません。これは単なる仮定の状況です)。上限は Number として決定されるだけで、下限は決定されません (## が存在する可能性があります)。 # ? extends Number
Integer)、したがって
? extends Number は
Integer の親クラスではありません上記のコードを変更します。少し変更すると正しくなります:
List<? super Number> list = new ArrayList<Object>(); // correct list.add(Integer.valueOf(1)); //correctまず第一に、反転のため、
Listda50108ad159903fabe211f1543600e8 は ## の親クラスです。 #ArrayLista87fdacec66f0909fc0757c19f2d2b1d。1 行は正しいです。
2 行目: ? super Number
は Integer
の親クラスです。理由は次のとおりです:
は特定の親クラスを表しますNumber の場合、 Serializable
または Object
の場合がありますが、どちらであっても、 Number の親クラスは Integer の親クラスでなければならないため、2 行目は次のようになります。これも正しいです Use extends それともスーパーですか?
java.util.Collections (JDK1.7) の copy メソッドから答えが得られます:
public static <T> void copy(List<? super T> dest, List<? extends T> src) { int srcSize = src.size(); if (srcSize > dest.size()) throw new IndexOutOfBoundsException("Source does not fit in dest"); if (srcSize < COPY_THRESHOLD || (src instanceof RandomAccess && dest instanceof RandomAccess)) { for (int i=0; i<srcSize; i++) dest.set(i, src.get(i)); } else { ListIterator<? super T> di=dest.listIterator(); ListIterator<? extends T> si=src.listIterator(); for (int i=0; i<srcSize; i++) { di.next(); di.set(si.next()); } } }
ジェネリックから変換するには クラスがデータを取得する場合は extends; を使用します
private static <E> E getFirst(List<? extends E> list){ return list.get(0); } private static <E> void setFirst(List<? super E> list, E firstElement){ list.add(firstElement); } public static void main(String[] args) { List<Integer> list = new ArrayList<Integer>(); setFirst(list, 1); Number number = getFirst(list); }
以上がJava ジェネリックスの共分散、反分散、拡張および超選択メソッドの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。