在学习Java泛型的时候,最重要的一个概念是泛型擦除,请看如下代码
public class Holder<T> {
private T item;
public void set(T t) {
item = t;
}
public T get() {
return item;
}
public static void main(String[] args) {
Holder<String> h = new Holder<>();
// 保存String对象
h.set("Hello");
// 打印类型参数
System.out.println(Arrays.toString(h.getClass().getTypeParameters()));
}
}
首先创建了一个泛型为String类型的Holder对象,然后保存了一个String对象,最后打印泛型的类型,正常来说,泛型类型应该是我们指定的String类型,然而结果如下
[T]
很可惜,它就是一个占位符,并不是String类型,这就是泛型擦除。
泛型擦除并不是说全部抹掉类型,而是擦除到第一个边界。我们可以通过 extends 或 super 来指定泛型边界,但是在这里泛型的边界为 Object。
让我们来验证下这里的泛型擦除是否是擦除到Object,我们可以测试是泛型对象是否可以调用Object的方法
public class Holder<T> {
private T item;
public void set(T t) {
item = t;
}
public T get() {
return item;
}
public String show() {
// 调用Object的toString()方法
return item.toString();
}
public static void main(String[] args) {
Holder<String> h = new Holder<>();
// 保存String对象
h.set("Hello");
// 打印类型参数
System.out.println(h.show());
}
}
在show()
方法中,泛型对象item
可以成功调用了Object类的toString()
方法,输出结果如下
Hello
但是除了Object的方法外,你真的调用不了任何方法,包含你传入的泛型类String的方法。