详解java 中泛型中的类型擦除和桥方法
程序员文章站
2023-12-11 18:30:22
在java中,泛型的引入是为了在编译时提供强类型检查和支持泛型编程。为了实现泛型,java编译器应用类型擦除实现:
&nb...
在java中,泛型的引入是为了在编译时提供强类型检查和支持泛型编程。为了实现泛型,java编译器应用类型擦除实现:
1、 用类型参数(type parameters)的限定(如果没有就用object)替换泛型类型中的所有类型参数。
2、 需要保持类型安全的时候插入类型转换(隐含插入)
3、 在extened 泛型类型中生成桥方法来保证多态性
类型擦除确保不会为已参数化了的类型(paramterized types)产生新类,这样泛型能保证没有运行时的负载。
泛型类型擦除
在类型擦除过程中,java编译器擦除所有类型参数,用它的限定或者object(没限定时)替换。
考虑下面的泛型类:
public class node<t> { private t data; private node<t> next; public node(t data, node<t> next) } this.data = data; this.next = next; } public t getdata() { return data; } // ... }
因为类型参数t是非限定的,java编译器使用object替换它:
public class node { private object data; private node next; public node(object data, node next) { this.data = data; this.next = next; } public object getdata() { return data; } // ... }
下面的例子,泛型node类使用了限定类型参数:
public class node<t extends comparable<t>> { private t data; private node<t> next; public node(t data, node<t> next) { this.data = data; this.next = next; } public t getdata() { return data; } // ...
编译器会使用第一个限定类,comparable替换限定参数类型t:
public class node { private comparable data; private node next; public node(comparable data, node next) { this.data = data; this.next = next; } public comparable getdata() { return data; } // ... }
同样,泛型方法也可以擦除。规则类似,不细说。
类型擦除的影响和桥方法
有时候类型擦除会引起无法预知的情况。比如:
给定以下两个类:
public class node<t> { public t data; public node(t data) { this.data = data; } public void setdata(t data) { system.out.println("node.setdata"); this.data = data; } } public class mynode extends node<integer> { public mynode(integer data) { super(data); } public void setdata(integer data) { system.out.println("mynode.setdata"); super.setdata(data); } }
考虑以下代码:
mynode mn = new mynode(5); node n = mn; // 原生类型 – 编译器会给出未检查警告 n.setdata("hello"); integer x = mn.data; // 会引发抛出classcastexception
类型擦除后,代码变成:
mynode mn = new mynode(5); node n = (mynode)mn; //原生类型 – 编译器会给出未检查警告 n.setdata("hello"); integer x = (string)mn.data; //会引发抛出classcastexception
public class node { public object data; public node(object data) { this.data = data; } public void setdata(object data) { system.out.println("node.setdata"); this.data = data; } } public class mynode extends node { public mynode(integer data) { super(data); } public void setdata(integer data) { system.out.println("mynode.setdata"); super.setdata(data); } }
类型擦除后,方法的签名已经不匹配。node 方法变成setdata(object),mynode方法变成setdata(integer)。mynode setdata方法已经不是覆盖node setdata方法。
为了解决这个问题,维持泛型类型的多态性,java编译器会生成一个桥方法:
class mynode extends node { // 编译器生成的桥方法 // public void setdata(object data) { setdata((integer) data); } public void setdata(integer data) { system.out.println("mynode.setdata"); super.setdata(data); } // ...
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
推荐阅读
-
详解java 中泛型中的类型擦除和桥方法
-
Java 中利用泛型和反射机制抽象DAO的实例
-
java中timer的schedule和scheduleAtFixedRate方法区别详解
-
Java 中利用泛型和反射机制抽象DAO的实例
-
详解java中的深拷贝和浅拷贝(clone()方法的重写、使用序列化实现真正的深拷贝)
-
详解.NET 4.0中的泛型协变(covariant)和反变(contravariant)
-
Java中成员变量与局部变量的区别、对象类型作为方法的参数和方法的返回值
-
Java中构造方法、空指针异常现象、基本数据类型和引用数据类型作为参数传递的区别
-
详解C# 泛型中的数据类型判定与转换
-
关于Java中泛型、反射和注解的扫盲篇