下面这段代码,在泛型JDK5之前常常看到
1 |
|
JDK5以后上面的代码发生了部分改变
1 |
|
其作用:
- 解决了转化类型的混乱
- 在编译期就检测类型是否正确
- 提高可读性
泛型可以使用到类与方法上。
泛型类
1 |
|
错误示范:
1 |
|
泛型方法
1 |
|
泛型的通配符
通配符分为:
- 无界通配符 <?> 任何参数类型都允许
-
有界通配符
i. 下界通配符 <? super T>,表示最低的类是T
ii. 上届通配符 <? extends T>,表示最高的类是T
1 |
|
就上面 list.add() 编译失败,我们可以采取写一个helper来解决
1 |
|
因为允许编译器将通配符的未知类型作为泛型方法的类型参数进行推断,所以上面不会出错。
1 |
|
其实对比上面对上界、下界通配符的操作,我们可以得到一个结论:
- 下界通配符,只存不取的时候使用
- 上界通配符,只取不存的时候使用
- 若既需要存又需要取,就避免使用通配符
泛型类型的擦除
1 |
|
上面这段代码,true or false? 结果是true,它们的类型被擦除了,只保留其原始类型(raw types)
jdk对类型擦除一段总结:
- 使用它们的边界替代所有的泛型参数,如果是无边界就使用 Object 替代。因此,产生的字节码仅包含普通的类,接口和方法。
- 必要时插入类型转化,以保持类型的安全性
- 在有继承的泛型类型中,生成桥方法(bridge methods)来维持多态
- Type erasure ensures that no new classes are created for parameterized types; consequently, generics incur no runtime overhead.
有边界的泛型类型
1 |
|
类型擦除带来的影响
1 |
|
Node的方法变成了setData(object)、而MyNode却是setData(Integer),这两个类的setData方法就不存在覆写(Override)了.
为了解决这个问题,类型擦除后保持泛型类型的多态性,编译器就会生成桥方法(bridge methods)确保事情如预期进行。
我们反编译MyNode.class会发现
1 |
|
When compiling a class or interface that extends a parameterized class or implements a parameterized interface, the compiler may need to create a synthetic(混合) method, called a bridge method, as part of the type erasure process.
参考: 1. Generics-oracle
对自己的现状不满意只有付出更多的努力去改变它
如果有不对的地方或建议,请指出,谢谢啦