由于java使用擦拭法来实现泛型,导致编译器把类型<T>
视为``Object,同时编译器根据
`的实际情况来实现安全的强制类型转换。也就是说,虚拟机看到字节码的时候对有没有泛型毫不知情,编译器编译的时候自动的完成了类型转换和检查的工作。
<T>
不能是基本类型,比如int
、double
等,因为泛型的实际类型是Object
,而Object
类型无法持有基本类型。无法取得带泛型的
Class
,因为<T>
是Object
类型,在编译后,所有泛型实例的getClass
返回的是同一个Class
实例。无法判断带泛型的
Class
。例如:
Pair<Integer> p = new Pair<>(123, 456); // Compile error: if (p instanceof Pair<String>.class) { } // 并不存在Pair<String>.class,而是只有唯一的Pair.class。
不能实例化
T
类型。例如:
public class Pair<T> { private T first; private T last; public Pair() { // Compile error: first = new T(); last = new T(); } } // first = new T();在擦拭后实际变成了first = new Object();这样的话,创建的所有泛型到头来全成Object了。
如果要实例化的话,需要借助
Class<T>
参数:public class Pair<T> { private T first; private T last; public Pair(Class<T> clazz) { first = clazz.newInstance(); last = clazz.newInstance(); } }
上述代码借助
Class
参数并通过反射来实例化T
类型,使用的时候,也必须传入Class
。例如:Pair<String> pair = new Pair<>(String.class);
Java的泛型是采用擦拭法实现的;
擦拭法决定了泛型<T>
:
不能是基本类型,例如:
int
;不能获取带泛型类型的
Class
,例如:Pair.class
;不能判断带泛型类型的类型,例如:
x instanceof Pair
;不能实例化
T
类型,例如:new T()
。
泛型方法要防止重复定义方法,例如:public boolean equals(T obj)
;
子类可以获取父类的泛型类型<T>
。
本文转载并精简自https://www.liaoxuefeng.com/wiki/1252599548343744/1265104600263968