Home > Java > javaTutorial > Why Does a List> Allow Different Types of Nested Lists?

Why Does a List> Allow Different Types of Nested Lists?

Patricia Arquette
Release: 2024-11-18 21:38:02
Original
1012 people have browsed it

Why Does a List<List<?>> Allow Different Types of Nested Lists? 
> Allow Different Types of Nested Lists? " />

Multiple Wildcards on Generic Methods Can Confuse the Java Compiler

The Problem:

Using multiple wildcards on generic methods can lead to confusion for both the Java compiler and the programmer. Consider the following example:

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!
    }
}
Copy after login

Two unrelated wildcards can be used to call doNothing with a List and a List. However, the following variation does not compile:

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

This behavior is expected because list1 and list2 refer to entirely different types.

Confusion arises with the following code:

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

This code compiles, but should it? It is possible to have a List> lol and a List list. Shouldn't the following modified code not compile?

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

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

The compiler seems to be doing its job, but confusion persists with the following variation:

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

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

Shouldn't this code not compile because it may involve a List> lol and a List list?

To clarify these behaviors, let's simplify the code back to LOLUnknowns1 and try to invoke probablyIllegal:

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!!
    }
}
Copy after login

Even with the same type for both wildcards, the code does not compile. However, a null type for the first argument compiles:

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!
    }
}
Copy after login

The Answer:

The confusion stems from a misunderstanding of what a nested wildcard, such as List>, actually means. Java Generics is invariant, meaning relationships among types do not hold for generic instantiations. This applies to nested lists as well:

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<?>>.
Copy after login

Therefore, a List> represents a list whose elements are lists of any type, not specifically the same type. This means that the following code is legal:

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

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

In Summary

The Java compiler's behavior with multiple generic wildcards is determined by capture conversion rules. Understanding the limitations of wildcard capture is crucial to avoid confusion.

The above is the detailed content of Why Does a List> Allow Different Types of Nested Lists?. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template