Java开发技术入门—Java泛型之泛型擦除
今天我们来讲解泛型中另一个重要知识点——泛型擦除!
泛型擦除概念
泛型信息只存在于代码编译阶段,但是在java的运行期(已经生成字节码文件后)与泛型相关的信息会被擦除掉,专业术语叫做类型擦除。我们来看一个例子:
ArrayList l1 = new ArrayList();
ArrayList l2 = new ArrayList();
System.out.println(l1.getClass()==l2.getClass());
运行代码,结果为True
这是因为ArrayList 和ArrayList 在 jvm 中的 Class 都是 List.class,二者在 jvm 中等同于List 。
通过下面的例子我们做进一步的分析
import java.lang.reflect.Field;
public class GeneErasure {
T object;
public GeneErasure(T object) {
this.object = object;
}
public static void main(String[] args) {
GeneErasure demo = new GeneErasure<String>("hi");
Class classz = demo.getClass();
System.out.println(classz.getName());
//输出com.my.generic.GeneErasure
Field[] fs = classz.getDeclaredFields();
for ( Field f:fs) {
System.out.println("feild: "+f.getName()+"type:"+f.getType().getName());
//输出feild: object type:java.lang.Object
}
}
通过这个例子我们可以看到Class 的类型仍然是GeneErasure并不是GeneErasure 这种形式,而类型T被替换成 Object 类型。接下来我们做另一个尝试,把GeneErasure 更改为 GeneErasure < T extends String>
输出结果为:
feild: object type:java.lang.String
所以,在泛型类被类型擦除的时候,之前泛型类中的类型参数部分如果没有指定上限,如则会被转译成普通的Object 类型,如果指定了上限,如则类型参数就被替换成类型上限。
利用类型擦除干“坏事儿”
大家都知道,下面这段代码l.add(123)无法编译通过,因为123不是String类型,这也是使用泛型的好处之一。
ArrayList l=new ArrayList();
l.add(“abc”);
l.add(123);
但是我们理解了泛型擦除的原理,我们可以巧妙地利用这个原理结合反射知识干一些“坏事”,例如:
ArrayListl=new ArrayList();
l.add("abc");
try {
Method method = l.getClass().getDeclaredMethod("add",Object.class);
method.invoke(l,"test");
method.invoke(l,100.f);
}catch (Exception e) {
e.printStackTrace();
}
System.out.println("list的大小是:"+l.size());
for ( Object o: l){
System.out.println(o);
}
运行结果是:
list的大小是:3
abc
test
100.0(被成功插入到ArrayList中)
我们可以看见100.0 成功地插入到ArrayList 中了,所以利用类型擦除的原理并结合反射的手段就绕过了正常开发中编译器不允许的操作限制。
通俗的理解
我们可以将泛型比作是一个看守,他来守护我们的代码安全,然后设置各项规定,“xxx 禁止出入”的提醒。而现实生活中,也总会有些人能够基于对门卫们生活作息的规律,绕开他们的监视(反射结合泛型擦除)来干一些坏事儿 。
文章来源:网络 版权归原作者所有
上文内容不用于商业目的,如涉及知识产权问题,请权利人联系小编,我们将立即处理
相关文章
- 大数据必学Java基础(五十一):什么是算法和数据结构
- Java中使用double转BigDecimal的问题
- java 登录 qq_Java实现QQ登录
- Java基础知识总结(超详细整理),java从入门到精通pdf「建议收藏」
- java后端开发需要学什么_从事Java后端开发,要学习哪些知识和技能?[通俗易懂]
- MySQL字段类型如何转为java_Java JDBC中,MySQL字段类型到JAVA类型的转换
- JAVA连接池
- java 随机数算法_Java随机数算法原理与实现方法实例详解
- Java入门代码_java编程自学网
- RabbitMQ基础介绍与在java中使用-入门「建议收藏」
- 【云驻共创】 JAVA常用的开发工具有哪些?
- java线程的创建和管理(一)
- java获取Spring中的bean方法总结详解编程语言
- 如何编写更好的java单元测试的7个技巧详解编程语言
- Java操作MySQL数据库快速入门(java访问mysql)
- 解决Java程序连接MySQL数据库的方法(java链接mysql数据库)
- 程序Linux下构建Java应用:从入门到精通(linux下开发java)
- 解析Java中的Linux路径(java中linux路径)
- MacOS下Java开发环境搭建指南(macos开发java)
- Java文件在Linux系统中的使用(java文件linux)
- Exploring the Power of Java MSSQL Integration for Efficient Data Management(javamssql)
- 询Java与Oracle联合查询更高效的数据处理方式(java oracle查)