java - 为什么有必要在泛型通配符中读取和 super 写入的情况下进行扩展?

标签 java generics

我很难理解泛型通配符的概念。

据我了解<?>引入未知类型来解决泛型不支持的协方差,它应该适合任何类型的集合和<?extends T>意味着您可以拥有类型的集合 T或扩展 T.<?super T> 的类意味着你可以拥有类型的集合 TT 的上级.

如有错误请指正

当我尝试这样写时:

import java.util.*;

public class Gclass {
    static Gclass t;

    public void write(List< ?super String > lw){
        lw.add("b");
    }

    public void read(List< ? extends String> lr){
        String s=lr.get(2);
        System.out.println(s);
    }

    public static void main(String[] args) {
        t=new Gclass();
        List<String> l=new ArrayList<String>();
        l.add("a");
        l.add("");
        System.out.println(l);
        t.write(l);
        System.out.println(l);
        t.read(l);
        System.out.println(l);
    }
}

它有效,但我怀疑的地方是:

  1. 根据我的理解,(extends 和 super)都包含声明的类型,所以在这个特殊情况下,我的 List类型为 String .我可以互换 extends 和 super,但出现编译错误?

  2. 如果写? super Object不管用?它应该工作,因为它是 String 的 super ?

  3. 我没有检查 read as String不能扩展,但我想我在这里也缺少一个概念。

我已经阅读了与此问题相关的所有关于 SO 的答案,但我仍然无法很好地理解它。

最佳答案

String 确实是一个不好的例子,因为它是 final类,但考虑像 Number 这样的东西相反。

如果方法采用 List<? extends Number> 类型的参数然后你可以传递一个 List<Number>List<Integer>List<BigDecimal>等等。因此,在方法主体中,可以将列表中的内容 取出(如您所知,它们必须是 Number 的实例),但您不能将任何内容放入 因为您不知道它是否安全(例如,编译器不能让您冒险将 Integer 放入 List<Float> 中)。

相反,如果该方法采用 List<? super Number>然后你可以传递一个 List<Number>List<Object> - 你不能从这个列表中取出任何东西,因为你不知道它是什么类型*,但你知道放置一个 Number 绝对是安全的

* 从技术上讲,您可以取出东西,但您可以将它们分配给的唯一类型是 Object

关于java - 为什么有必要在泛型通配符中读取和 super 写入的情况下进行扩展?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21209830/

相关文章:

ios - 具有关联类型要求和默认实现的 Swift 协议(protocol)

c# - 是否可以将多个通用类型参数传递给一个方法?

Java8 : ambiguity with lambdas and overloaded methods

java - 贪心算法Java/firstFit方法

java - 在 Tomcat 上部署的 WAR 中的 JPA 功能

java - Gson fromJson 使用通用父类(super class)

java - 为 RCP 应用程序构建更新站点的最佳方式

java - 解码扩展抽象泛型类的类

java - 如何在android java中将多个gridviews添加到一个scrollview?

generics - 如何使结构字段成为泛型类型