JAVA泛型中通配符到底是什么东西

比如有这样一个泛型类

public class Gen<T>{
    
}

然后在其他类中有这样一个方法

public void showKeyValue(Gen gen){}

public void showKeyValue(Gen<?> gen){}

还有,为什么Gen<Object>和Gen<String>是同一种类(Gen<Object>.Class = Gen<String>.class)
但是Gen<String>却不能指向Gen<Object>的引用(Gen<Object> gen = new Gen<String>会报错)
这两种方法有什么区别吗,如果没有,那么这个的意义在哪呢?
新手,希望能有大神解释下

阅读 1.7k
1 个回答

官方文档 中有写这个问题. 这里做一把搬运工, 大致翻译如下:

无界通配符(unbounded wildcard)在以下两种场景下使用:

  • 如果你在函数中需要调用 Object 类中的方法, 比如 toString().
  • 如果代码不依赖于具体的类型. 典型的例子是 Class<?>: Class<T> 类中的多数方法都不需要知道 T 的类型.

关于第一种情况的例子, 有如下方法, 用来打印 List 中的元素信息:

public static void printList(List<Object> list) {
    for (Object elem : list)
        System.out.println(elem + " ");
    System.out.println();
}

但上面的函数输出的是一串内存地址, 而不是 toString() 方法的内容: 它无法正确打印 List<Integer>, List<String> 等列表的值, 因为这些列表并非 List<Object> 的子类型. 使用 List<?> 可以解决这个问题:

public static void printList(List<?> list) {
    for (Object elem: list)
        System.out.print(elem + " ");
    System.out.println();
}

因为 List<A>List<?> 的子类型, 所以上面函数可以正常打印任何类型的列表:

List<Integer> li = Arrays.asList(1, 2, 3);
List<String>  ls = Arrays.asList("one", "two", "three");
printList(li);
printList(ls);

注意: List<Object>List<?> 也有区别: 前者可插入任何 Object 子类, 后者只能插入 null, 原因见 官方文档中的通配符使用指南.


刚刚看到你还有第二个问题. Gen<Object> gen = new Gen<String> 会报错, 这个问题很好理解: gen.add(new Object()) 这种操作是非法的, 因为新添加的 Object 实例未必是 String 实例.

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题