Heim >Java >javaLernprogramm >Warum erlaubt eine List> verschiedene Arten verschachtelter Listen?

Warum erlaubt eine List> verschiedene Arten verschachtelter Listen?

Patricia Arquette
Patricia ArquetteOriginal
2024-11-18 21:38:021013Durchsuche

Why Does a List<List<?>> Verschiedene Arten verschachtelter Listen zulassen? 
> Verschiedene Arten verschachtelter Listen zulassen? " />

Mehrere Platzhalter bei generischen Methoden können den Java-Compiler verwirren

Das Problem:

Die Verwendung mehrerer Platzhalter bei Generische Methoden können sowohl beim Java-Compiler als auch beim Programmierer zu Verwirrung führen:

public class TwoListsOfUnknowns {
    static void doNothing(List<?> list1, List<?> list2) {}

    public static void main(String[] args) {
        List<String> list1 = null;
        List<Integer> list2 = null;
        doNothing(list1, list2); // compiles fine!
    }
}

Zwei unabhängige Platzhalter können verwendet werden, um doNothing mit einem List aufzurufen. . Die folgende Variante wird jedoch nicht kompiliert:

public class TwoListsOfUnknowns2 {
    static void doSomethingIllegal(List<?> list1, List<?> list2) {
        list1.addAll(list2); 
            // DOES NOT COMPILE!!!
    }
}

Dieses Verhalten ist zu erwarten, da list1 und list2 auf völlig unterschiedliche Typen verweisen.

Verwechslung entsteht mit dem folgenden Code:

public class LOLUnknowns1 {
    static void probablyIllegal(List<List<?>> lol, List<?> list) {
        lol.add(list); // this compiles!! how come???
    }
}

Dieser Code wird kompiliert, aber es ist möglich, eine List>-Liste zu haben. Sollte der folgende geänderte Code nicht kompiliert werden?

public class LOLUnknowns2 {
    static void rightfullyIllegal(
            List<List<? extends Number>> lol, List<?> list) {

        lol.add(list); // DOES NOT COMPILE! As expected!!!
    }
}

Der Compiler scheint seinen Job zu machen, aber die Verwirrung besteht weiterhin mit der folgenden Variante:

public class LOLUnknowns3 {
    static void probablyIllegalAgain(
            List<List<? extends Number>> lol, List<? extends Number> list) {

        lol.add(list); // compiles fine!!! how come???
    }
}

Sollte dieser Code nicht kompiliert werden, da es sich möglicherweise um eine List> handelt ; lol und eine List-Liste?

Um diese Verhaltensweisen zu verdeutlichen, vereinfachen wir den Code wieder auf LOLUnknowns1 und versuchen, „wahrscheinlichIllegal:“ aufzurufen, sogar mit demselben Typ für beide Platzhalter, der Code wird nicht kompiliert. Allerdings kompiliert ein Nulltyp für das erste Argument:

public class LOLUnknowns1a {
    static void probablyIllegal(List<List<?>> lol, List<?> list) {
        lol.add(list); // this compiles!! how come???
    }

    public static void main(String[] args) {
        List<List<String>> lol = null;
        List<String> list = null;
        probablyIllegal(lol, list); // DOES NOT COMPILE!!
    }
}

Die Antwort:
public class LOLUnknowns1b {
    static void probablyIllegal(List<List<?>> lol, List<?> list) {
        lol.add(list); // this compiles!! how come???
    }

    public static void main(String[] args) {
        List<String> list = null;
        probablyIllegal(null, list); // compiles fine!
    }
}

Die Verwirrung rührt von einem Missverständnis darüber her, was ein verschachtelter Platzhalter, wie z. B. List< ;Liste>, bedeutet eigentlich. Java Generics ist invariant, was bedeutet, dass Beziehungen zwischen Typen für generische Instanziierungen nicht gelten. Dies gilt auch für verschachtelte Listen:

Daher ist eine Liste> stellt eine Liste dar, deren Elemente Listen beliebigen Typs sind, nicht unbedingt denselben Typ. Dies bedeutet, dass der folgende Code zulässig ist:

A List<String> is (captureable by) a List<?>.
A List<List<String>> is NOT (captureable by) a List<List<?>>.
A List<List<String>> IS (captureable by) a List<? extends List<?>>.

Zusammenfassung
List<List<?>> lolAny = new ArrayList<>();

lolAny.add(new ArrayList<Integer>());
lolAny.add(new ArrayList<String>());

Das Verhalten des Java-Compilers mit mehreren generischen Platzhaltern wird durch Capture-Konvertierungsregeln bestimmt. Um Verwirrung zu vermeiden, ist es wichtig, die Einschränkungen der Wildcard-Erfassung zu verstehen.

Das obige ist der detaillierte Inhalt vonWarum erlaubt eine List> verschiedene Arten verschachtelter Listen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn