无界通配符<?>很容易和原生类型混淆。

以List为例:

List表示持有任何Object类型的原生List,其实就等价于List<Object>

List<?>表示某种具有特定类型的非原生List(同构集合),只是我们不知道它的具体类型是什么,所以我们就不允许往里set数据

看下面例子:

 public class Wildcards {

     // 这里Holder等价于Holder<Object>,Holder<Object>没警告但下面的方法调用时除第一个都会报ERROR,Holder会有警告
static void saveData(Holder holder, Object arg) {
holder.set(arg); // [Warning] Type safety: The method set(Object) belongs to the raw type Holder. References to generic type Holder<T> should be parameterized
Object obj = holder.get();
System.out.println(obj.getClass().getSimpleName() + ": " + obj.toString());
} // 因为不知道Holder<?>的具体类型是什么,所以我们就不允许往里set数据
static void saveDataError(Holder<?> holder, Object arg) {
// holder.set(arg); // [Compile Error] The method set(capture#1-of ?) in the type Holder<capture#1-of ?> is not applicable for the arguments (Object)
// holder.set(new Wildcards()); // Same Compile Error
Object obj = holder.get();
System.out.println(obj.getClass().getSimpleName() + ": " + obj.toString());
} public static void main(String[] args) {
Holder h1 = new Holder<Long>();
Holder<Long> h2 = new Holder<Long>();
Holder<?> h3 = new Holder<Long>();
Holder<? extends Long> h4 = new Holder<Long>(); saveData(h1, 1L); // Long: 1
saveData(h2, 2L); // Long: 2
saveData(h3, 3L); // Long: 3
saveData(h4, 4L); // Long: 4 saveDataError(h1, 5L); // Long: 1
saveDataError(h2, 6L); // Long: 2
saveDataError(h3, 7L); // Long: 3
saveDataError(h4, 8L); // Long: 4
}
} class Holder<T> {
private T value;
public Holder() { }
public Holder(T val) { value = val; }
public void set(T val) { value = val; }
public T get() { return value; }
@Override public boolean equals(Object obj) { return value.equals(obj); }
}

捕获转换技术

如果向一个使用<?>的方法传递原生类型,那么对于编辑器来说,可能会推断出实际的类型参数,使得这个方法可以调用另一个使用确切类型的的方法。下面是一个例子:

 public class CaptureConversion {

     static <T> void getData(Holder<T> holder) {
T t = holder.get();
System.out.println(t.getClass().getSimpleName() + ": " + t);
} static void chapterGet(Holder<?> holder) {
getData(holder);
} public static void main(String[] args) {
Holder h1 = new Holder<Long>(1L);
chapterGet(h1); // Long: 1
}
}

Java泛型(7):无界通配符<?>的更多相关文章

  1. Java泛型解析(02):通配符限定

    Java泛型解析(02):通配符限定      考虑一个这种场景.计算数组中的最大元素. [code01] public class ArrayUtil { public static <T&g ...

  2. JAVA泛型之<? extends T>:(通配符上限)和<? super T>(通配符下限)

    一.通配符上限和通配符下限接受的类型 通配符上限:<? extends T> 通配符下限:<? super T> 以下代码是测试结果,注释为解释说明 package xayd. ...

  3. Java泛型之上、下界通配符的理解(适合初学)

    泛型的由来 为什么需要泛型   Java的数据类型一般都是在定义时就需要确定,这种强制的好处就是类型安全,不会出现像弄一个ClassCastException的数据给jvm,数据安全那么执行的clas ...

  4. 什么情况下不能使用 Java 泛型

    1. 前言 Java 1.5 引入了泛型来保证类型安全,防止在运行时发生类型转换异常,让类型参数化,提高了代码的可读性和重用率.但是有些情况下泛型也是不允许使用的,今天就总结一下编码中不能使用泛型的一 ...

  5. Java 泛型和通配符解惑

    转自:http://www.linuxidc.com/Linux/2013-10/90928.htm T  有类型 ?  未知类型 一.通配符的上界 既然知道List<Cat>并不是Lis ...

  6. Java 泛型 通配符类型

    Java 泛型 通配符类型 @author ixenos 摘要:限定通配符类型.无限定通配符类型.与普通泛型区别.通配符捕获 通配符类型 通配符的子类型限定(?都是儿孙) <? extends ...

  7. java泛型通配符?

    转自:http://www.linuxidc.com/Linux/2013-10/90928.htm T  有类型 ?  未知类型 一.通配符的上界 既然知道List<Cat>并不是Lis ...

  8. JAVA 泛型中的通配符 T,E,K,V,?

    前言 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许开发者在编译时检测到非法的类型. 泛型的本质是参数化类型,也就是说所操作的数据 ...

  9. 【转】聊一聊-JAVA 泛型中的通配符 T,E,K,V,?

    原文:https://juejin.im/post/5d5789d26fb9a06ad0056bd9 前言 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型 ...

随机推荐

  1. git的安装和简单使用

    目前windows版本的git有几种实现,但我们选择msysgit发行版,这是目前做得兼容性最好的. 下载地址: http://code.google.com/p/msysgit/downloads/ ...

  2. python 中的GIL (全局解释器锁)详解

    1.GIL是什么? GIL全称Global Interpreter Lock,即全局解释器锁. 作用就是,限制多线程同时执行,保证同一时间内只有一个线程在执行. GIL并不是Python的特性,它是在 ...

  3. 【转】Everything you need to know about NoSQL databases

    原文: https://dev.to/lmolivera/everything-you-need-to-know-about-nosql-databases-3o3h ---------------- ...

  4. string::c_str

    const char* c_str() const noexcept;功能:返回c风格字符转 #include <iostream>#include <string>#incl ...

  5. Spring源码解读(一)

    前期准备 首先搭建一个简单的Spring Demo工程 项目目录结构如下图所示: applicationContect.xml (可以取其他文件名,只要在加载配置文件时指定文件路径) <?xml ...

  6. flask调试模式

    想要启用调试模式,发现安装目前网上流行的两种方式均无法在Pycharm中打开调试模式. 1)直接在对象上设置 flask 更新到1.0以后 不支持使用debug =True 来开启调试模式了. Pri ...

  7. yii框架学习(获取插入后的id)

    插入单条数据, 获取插入数据的id. $model->attributes['id']; new  model 添加数据的时候, 需要注意, 如果是想要循环添加多条数据的情况, new mode ...

  8. Mybatis resultMap和resultType的区别

    resultType和resultMap功能类似  ,都是返回对象信息  ,但是resultMap要更强大一些 ,可自定义.因为resultMap要配置一下,表和类的一一对应关系,所以说就算你的字段名 ...

  9. Codeforces Round #346 (Div. 2) C题

    C. Tanya and Toys In Berland recently a new collection of toys went on sale. This collection consist ...

  10. 初次接触python,怎么样系统的自学呢?

    关注专栏 写文章登录   给伸手党的福利:Python 新手入门引导 Crossin 2 个月前 这是一篇 Python 入门指南,针对那些没有任何编程经验,从零开始学习 Python 的同学.不管你 ...