Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the compiler treat List<?> and List<? extends Object> differently?

Tags:

java

generics

Consider the following code:

import java.util.ArrayList;
import java.util.List;

public class UnboundedWildcardProblem {

    public static void main(String[] args) {
        List<?> a = new ArrayList();
        List<? extends Object> b = new ArrayList();
    }
}

The creation of List<?> doesn't produce any warnings, but the creation of List<? extends Object> produces an unchecked warning:

Warning: java: unchecked conversion
  required: java.util.List<? extends java.lang.Object>
  found:    java.util.ArrayList

I searched for possible reasons and found some discussions:

List<?> vs List<? extends Object>

What's the difference between <?> and <? extends Object> in Java Generics?

But after reading these discussions it seems to me that List<?> and List<? extends Object> are the same thing.

So, what is the reason for such compiler behaviour?

EDIT:

The single flag used for compilation was an Xlint:unchecked flag.

like image 915
Edgar Rokjān Avatar asked Nov 18 '15 22:11

Edgar Rokjān


1 Answers

The creation of List<?> doesn't produce any warnings, but the creation of List<? extends Object> produces an unchecked warning

In fact, if you compile your code with the -Xlint:all or just Xlint option, you would get a warning for the List<?> a = new ArrayList(); statement, something like:

   warning: [rawtypes] found raw type: ArrayList
            List<?> a = new ArrayList();
                            ^
missing type arguments for generic class ArrayList<E>
where E is a type-variable:
  E extends Object declared in class ArrayList

However, the reason why you're not getting an unchecked warning per se is because the type List<?> contains only unbounded wildcards as mentioned in this section from the Java Language Specification:

There is an unchecked conversion from the raw class or interface type (§4.8) G to any parameterized type of the form G<T1,...,Tn>.

...

Use of an unchecked conversion causes a compile-time unchecked warning unless all type arguments Ti (1 ≤ i ≤ n) are unbounded wildcards (§4.5.1), or the unchecked warning is suppressed by the SuppressWarnings annotation (§9.6.4.5).

However in this section, it is mentioned:

The wildcard ? extends Object is equivalent to the unbounded wildcard ?.

which shows a subtle inconsistency in the compiler.

like image 172
M A Avatar answered Oct 22 '22 15:10

M A