Heim  >  Artikel  >  Java  >  Kovarianz-, Kontravarianz-, Erweiterungs- und Superselektionsmethoden von Java-Generika

Kovarianz-, Kontravarianz-, Erweiterungs- und Superselektionsmethoden von Java-Generika

PHPz
PHPznach vorne
2023-05-26 13:46:121243Durchsuche

Um Kovarianz und Kontravarianz zu verstehen, müssen wir zunächst Folgendes einführen:

Wenn C eine Unterklasse von P ist, kann P gemäß dem Liskov-Substitutionsprinzip C ersetzen, das heißt P p = new C();
C erbt von P, aufgezeichnet als C 23b6ec0f353510d49b3d2b90e8b44360 und Listc0f559cc8d56b43654fcbe4aa9df7b4a angesehen werden. Es gibt keine Vererbungsbeziehung

Was ist Kovarianz?

Wenn F kovariant ist, wenn C fd4888e8331f4fa99820f314ae77550c 和Listc0f559cc8d56b43654fcbe4aa9df7b4a 不存在任何继承关系

什么是协变

如果F是协变的,当 C 3592d2c0d3e58f8105bc39ac7b94d518可以看作为ArrayListc0f559cc8d56b43654fcbe4aa9df7b4a的父类

? extend Number可以看作为一个类型范围,表示Number的某一个子类

数组默认是协变的

Number[] numbers = new Integer[3];

什么是逆变

如果F是逆变的,当 C 5d18509ffa87f09498721c15444d4b70= F(P)

Java 提供了一个super来将不变转为协变,例如:

List<? super Number> list = new ArrayList<Object>(1);  //corrent

此时的 Listda50108ad159903fabe211f1543600e8可以看作为 ArrayLista87fdacec66f0909fc0757c19f2d2b1d的父类

extends 和 super

首先,我们看看Collection.add的实现:

public interface List<E> extends Collection<E> { boolean add(E e); }

下面代码将会报错?? extends NumberInteger类型不匹配

List<? extends Number> list = new ArrayList<Integer>(); // correct
list.add(Integer.valueOf(1));  //error

首先在调用add方法时,泛型E自动变成了a2b037db85f4e1df0e812b9647ac55a8

第二行报错,也就是说? extends Number不是Integer的父类。这里要将 Lista2b037db85f4e1df0e812b9647ac55a8ArrayListc0f559cc8d56b43654fcbe4aa9df7b4a的父类区分开。

? extends Number可以看作为一个类型范围中某一个类型,表示Number的某一个子类,但又没明确是哪个子类,可能是Float,可能是Short,也可能是Integer的子类(Integer被final修饰,不可能有子类,这里只是一种假设情况),它只确定了它的上界为 Number,并没有确定下界(有可能存在? extends NumberInteger),因此 ? extends Number不是Integer的父类

将上面代码稍做修改就正确了:

List<? super Number> list = new ArrayList<Object>(); // correct
list.add(Integer.valueOf(1));  //correct

首先因为逆变,Listda50108ad159903fabe211f1543600e8ArrayLista87fdacec66f0909fc0757c19f2d2b1d的父类,第一行正确。

第二行: ? super NumberInteger的父类,原因是:? super Number表示Number的某一个父类,可能是Serializable也可能是 ObjectAn dieser Stelle Zeit kann Lista2c08abdf84903e86dd3ad0187900e0f als übergeordnete Klasse von ArrayListc0f559cc8d56b43654fcbe4aa9df7b4a angesehen werden ein Typbereich, der eine bestimmte Unterklasse darstellt. Das Array ist standardmäßig kovariant. Was ist Kontravarianz? Wenn F kontravariant ist und C 5aaf8c27f6d4179a6818d1f0035130fa = F(P)

Java bietet eine Super zum Konvertieren von Invarianz in Kovarianz, zum Beispiel:

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

Zu diesem Zeitpunkt kann Listda50108ad159903fabe211f1543600e8 als ArrayLista87fdacec66f0909fc0757c19f2d2b1ds übergeordnete Klasse <ul class=" list-paddingleft-2"> <li>extends und super<p></p> </li>Schauen wir uns zunächst die Implementierung von Collection.add an: <li><p><pre class="brush:java;">private static &lt;E&gt; E getFirst(List&lt;? extends E&gt; list){ return list.get(0); } private static &lt;E&gt; void setFirst(List&lt;? super E&gt; list, E firstElement){ list.add(firstElement); } public static void main(String[] args) { List&lt;Integer&gt; list = new ArrayList&lt;Integer&gt;(); setFirst(list, 1); Number number = getFirst(list); }</pre></p></li>Wird der folgende Code einen Fehler melden? <li> <code>? extensions Number stimmt nicht mit dem Typ von Integer überein

rrreee

Zuallererst wird beim Aufruf der Add-Methode automatisch das generische E verwendet 3118fc83eaba9bc6a738268c3148a1a2 Die zweite Zeile meldet einen Fehler, was bedeutet, dass ? erweitert Nummer nicht die übergeordnete Klasse von Integer ist. Hier müssen wir unterscheiden, dass List5a1312bd1de15616f5bbc24ce87c8691 die übergeordnete Klasse von ArrayListc0f559cc8d56b43654fcbe4aa9df7b4a ist. 🎜🎜? extensions Number kann als ein bestimmter Typ in einem Typbereich betrachtet werden, der eine bestimmte Unterklasse von Number darstellt, aber es ist nicht klar, um welche Unterklasse es sich handelt. Es kann sich um Float oder Short handeln , oder es ist eine Unterklasse von Integer (Integer wird durch final geändert und kann keine Unterklassen haben. Dies ist nur eine hypothetische Situation. Es bestimmt nur seine Obergrenze als Zahl und nicht die Untergrenze (es kann ? erweitert Number < Integer, also ist ? erweitert Number nicht die übergeordnete Klasse von Integer Ändern Sie den obigen Code und er wird korrekt sein. Fehler: 🎜🎜rrreee🎜Zuallererst ist Listda50108ad159903fabe211f1543600e8 die übergeordnete Klasse von ArrayLista87fdacec66f0909fc0757c19f2d2b1d code>, und die erste Zeile ist korrekt. 🎜🎜Die zweite Zeile: <code>? super Number ist die übergeordnete Klasse von Integer. Der Grund ist: ? super Number stellt eine bestimmte übergeordnete Klasse dar Zahl. Es kann Serializable oder Object sein, aber egal um welche es sich handelt, die übergeordnete Klasse von Number muss die übergeordnete Klasse von Integer sein, daher ist auch die zweite Zeile korrekt . Soll ich „Extens“ oder „Super“ verwenden? 🎜🎜🎜Die Kopiermethode von java.util.Collections (JDK1.7) gibt uns die Antwort: 🎜🎜rrreee🎜🎜🎜Wenn Sie Daten von einer generischen Klasse erhalten möchten, verwenden Sie „Extens“; 🎜🎜🎜🎜Um Daten in eine generische Klasse zu schreiben, verwenden Sie „super“;

Das obige ist der detaillierte Inhalt vonKovarianz-, Kontravarianz-, Erweiterungs- und Superselektionsmethoden von Java-Generika. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen