Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why this java snippet code compile just fine?

Tags:

java

generics

1.1 example

import java.util.*;

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

How come this 1.1 code compile if we may end up having List<List<Integer>> lol and a List<String> list?

this following code snippet: 1.2 example

import java.util.*;

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

1.1 example baffles me, how is that possible to be compiled just fine?

I wnat to know the specific reason why a code compiled when it was expected not to from my understanding

like image 898
Euler eulerhenriuqe Avatar asked Sep 06 '25 21:09

Euler eulerhenriuqe


1 Answers

How come this 1.1 code compile if we may end up having List<List<Integer>> lol and a List<String> list?

You can not pass a List<List<Integer>> to an argument of type List<List<?>>. If you try:

probablyIllegal(new ArrayList<List<Integer>>(), new ArrayList<String>());

you get

The method probablyIllegal(List<List<?>>, List<?>) in the type LOLUnknowns1 is not applicable for the arguments (ArrayList<List<Integer>>, ArrayList<String>).

The reason is that even though a List<Integer> is a subtype of List<?>, List<List<Integer>> is not a subtype of List<List<?>>, just like, even though String is a subtype of Object, List<String> is not a subtype of List<Object>.

If you want to be able to pass a List<List<Integer>>, you need to declare the argument to be of type List<? extends List<?>>:

static void probablyIllegal(List<? extends List<?>> lol, List<?> list) {
    lol.add(list); 
}

After that change, the compiler will accept your call, but reject your method implementation:

The method add(capture#1-of ? extends List<?>) in the type List<capture#1-of ? extends List<?>> is not applicable for the arguments (List<capture#2-of ?>)

The error message is a bit cryptic (you need to read up on wildcard capture to understand it), but it basically says that you can't add the List<?> to a List<? extends List<?>> because you don't know what kind of elements lol contains, and therefore can not know that list is of a compatible type.

To conclude, you can either specify a specific element type for the List, in which case you can add, but not use a List of a different type, or you can leave the element type of the List unspecified, in which case you can use any List, but not add anything to it. Either way, nothing bad happens.

like image 109
meriton Avatar answered Sep 08 '25 11:09

meriton