List<? super T>List<? extends T>有什么区别?

我过go 使用List<? extends T>,但它不允许我向其添加元素list.add(e),而List<? super T>可以.

推荐答案

扩展

通配符声明为List<? 扩展 Number> foo3意味着其中任何一项都是合法转让:

List<? 扩展 Number> foo3 = new ArrayList<Number>();  // Number "扩展" Number (in this context)
List<? 扩展 Number> foo3 = new ArrayList<Integer>(); // Integer 扩展 Number
List<? 扩展 Number> foo3 = new ArrayList<Double>();  // Double 扩展 Number
  1. Reading-鉴于上述可能的赋值,你保证从List foo3中读取什么类型的对象:

    • 您可以读取100,因为可以分配给foo3的任何列表都包含NumberNumber的子类.
    • 你不能读Integer,因为foo3可能指向List<Double>.
    • 你不能读Double,因为foo3可能指向List<Integer>.
  2. Writing-鉴于上述可能的转让,您可以在List foo3中添加哪种类型的物品,这对于all上述可能的ArrayList转让是合法的:

    • 不能添加Integer,因为foo3可能指向List<Double>.
    • 您不能添加Double,因为foo3可能指向List<Integer>.
    • 您不能添加Number,因为foo3可能指向List<Integer>.

You can't add any object to 100 because you can't guarantee what kind of 101 it is really pointing to, so you can't guarantee that the object is allowed in that 101. The only "guarantee" is that you can only read from it and you'll get a 103 or subclass of 103.

超级的

现在考虑List <? 超级的 T>个.

通配符声明List<? 超级的 Integer> foo3表示其中任何一个都是合法分配:

List<? 超级的 Integer> foo3 = new ArrayList<Integer>();  // Integer is a "超级的class" of Integer (in this context)
List<? 超级的 Integer> foo3 = new ArrayList<Number>();   // Number is a 超级的class of Integer
List<? 超级的 Integer> foo3 = new ArrayList<Object>();   // Object is a 超级的class of Integer
  1. Reading-鉴于上述可能的分配,当你阅读List foo3时,你保证会收到什么类型的对象:

    • 你不能保证得到Integer分,因为foo3可能指向List<Number>List<Object>.
    • 你不能保证得Number分,因为foo3可能指的是List<Object>分.
    • only的保证是您将获得100的实例或Object的子类(但是您不知道是哪个子类).
  2. Writing-鉴于上述可能的转让,您可以在List foo3中添加哪种类型的物品,这对于all上述可能的ArrayList转让是合法的:

    • 您可以添加Integer,因为上述任何列表中都允许使用Integer.
    • 您可以添加Integer子类的实例,因为在上述任何列表中都允许Integer子类的实例.
    • 您不能添加Double,因为foo3可能指向ArrayList<Integer>.
    • 不能添加Number,因为foo3可能指向ArrayList<Integer>.
    • 您不能添加Object,因为foo3可能指向ArrayList<Integer>.

佩克斯

记住佩克斯:"Producer Extends, Consumer Super".

  • "Producer Extends"-如果你需要一个List来产生T个值(你想从列表中读取T),你需要用? 扩展 T来声明它,例如List<? 扩展 Integer>.但是你不能添加到这个列表中.

  • "Consumer Super"-如果您需要List来使用T个值(您想要将T写入列表),则需要用? 超级的 T来声明它,例如List<? 超级的 Integer>.但不能保证您可以从此列表中读取哪种类型的对象.

  • 如果需要对列表进行读写操作,则需要准确地声明列表,不使用通配符,例如List<Integer>.

实例

this example from the Java Generics FAQ.注意源列表src(生产列表)如何使用扩展,目的地列表dest(消费列表)如何使用超级的:

public class Collections { 
  public static <T> void copy(List<? 超级的 T> dest, List<? 扩展 T> src) {
      for (int i = 0; i < src.size(); i++) 
        dest.set(i, src.get(i)); 
  } 
}

也看到

Java相关问答推荐

如果您仅同步写操作,Java布尔线程是否安全

Java Swing绘制gif作为多个JSYS和JLabels的背景

如何让HikariCP指标在NewRelic中正确显示?

如何审查Java dtos中的自定义注释字段?

Javascript更新alert 可扩展内容样式与CSS—按钮更多/更少

空手道比赛条件

H2弹簧靴试验跌落台

即使我正在使用并发方法,使用Javascript的应用程序也会继续冻结'

neo4j java驱动程序是否会在错误发生时自动回滚事务?

Kubernetes的Java客户端检索状态.处于终止状态的Pod的阶段';正在运行';

如何创建同一类的另一个对象,该对象位于变量中?

Java LocalTime.parse在本地PC上的Spring Boot中工作,但在Docker容器中不工作

Com.google.firebase.database.DatabaseException:无法将类型为java.lang.Boolean的值转换为字符串.这是关于什么的?

如何从日志(log)行中删除包名称?

try 从REST API返回对象列表时出错

扩展视图高度,并将其拖动到较低的视图上,而不是将其向下推?

为什么有两种实现来检索数组类的组件类型?

从泛型枚举创建EnumMap

为什么JavaFX MediaPlayer音频播放在Windows和Mac上运行良好,但在Linux(POPOS/Ubuntu)上却有问题?

rest api服务 spring 启动中出现IllegalFormatConversionException