简体   繁体   English

在 Java 中导致编译错误的上限通配符

[英]Upper bounded wildcards causing compilation error in Java

I cannot understand why I am getting these compilation errors:我不明白为什么我会收到这些编译错误:

1: 1:

The method add(capture#1-of ? extends Exec.Bird) in the type List is not applicable for the arguments (Exec.Sparrow)类型列表中的 add(capture#1-of ? extends Exec.Bird) 方法不适用于参数 (Exec.Sparrow)

2: 2:

The method add(capture#2-of ? extends Exec.Bird) in the type List is not applicable for the arguments (Exec.Bird)类型列表中的方法 add(capture#2-of ? extends Exec.Bird) 不适用于参数 (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> 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 . List<? extends Bird>您实际上说的是属于 Bird 子类型的任何类型,或者更准确地说,是属于Bird子类型的未知但特定类型 It's not the same as saying every type that extends Bird .这与说扩展Bird每种类型不同

That means that ?那是?意思? can be a Sparrow , but it can also be a Blackbird .可以是Sparrow ,也可以是Blackbird If you try to add a Sparrow to a list that could contain only Blackbird s, it won't work.如果您尝试将Sparrow添加到只能包含Blackbird的列表中,它将不起作用。 For that same reason you cannot add a Bird to a list that could be a List of Sparrow s.出于同样的原因,您不能将Bird添加到可能Sparrow列表的列表中。

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 .关于这个下限示例:声明实际上是说任何类型是Bird或其超类之一 That means that you can safely add a Sparrow or a Bird , because both meet those criteria.这意味着您可以安全地添加SparrowBird ,因为两者都符合这些标准。

Generally speaking, you should use ? super ...一般来说,你应该使用? super ... ? super ... when you are writing to the list, and ? extends ... ? super ...当你写到列表中时,和? extends ... ? extends ... when you are reading from the list. ? extends ...当您从列表中阅读时。 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:您可以像这样实例化birds列表:

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());
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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