简体   繁体   中英

Upper bounded wildcards causing compilation error in Java

I cannot understand why I am getting these compilation errors:

1:

The method add(capture#1-of ? extends Exec.Bird) in the type List is not applicable for the arguments (Exec.Sparrow)

2:

The method add(capture#2-of ? extends Exec.Bird) in the type List is not applicable for the arguments (Exec.Bird)

static class Bird{}
static class Sparrow extends Bird{}

public static void main(String[] args){
    List<? extends Bird> birds = new ArrayList<Bird>();
    birds.add(new Sparrow()); //#1 DOES NOT COMPILE
    birds.add(new Bird());// //#2 DOES NOT COMPILE
}

With List<? extends Bird> List<? extends Bird> you actually say any type that is a subtype of Bird , or, more accurately, an unknown, but specific type that is a subtype of Bird . It's not the same as saying every type that extends Bird .

That means that ? can be a Sparrow , but it can also be a Blackbird . If you try to add a Sparrow to a list that could contain only Blackbird s, it won't work. For that same reason you cannot add a Bird to a list that could be a List of Sparrow s.

In order to make things work, you just change the declaration of the list to this:

List<Bird> birds = new ArrayList<>();

or use lower bound:

List<? super Bird> birds = new ArrayList<>();

About this lower bound example: the declaration actually says any type that is a Bird or one of its superclasses . That means that you can safely add a Sparrow or a Bird , because both meet those criteria.

Generally speaking, you should use ? super ... ? super ... when you are writing to the list, and ? extends ... ? extends ... when you are reading from the list. If you are both reading and writing, you shouldn't use bounds.


This answer provides very useful information about generics. You definitely should read it.

You can instantiate the birds list like this:

List<Bird> birds = new ArrayList<>();

Full code:

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

public class Main {
    static class Bird{}
    static class Sparrow extends Bird{}

    public static void main(String[] args) {
        List<Bird> birds = new ArrayList<>();
        birds.add(new Sparrow());
        birds.add(new Bird());
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM