章
目
录
Java面试题:谈谈你对泛型、泛型擦除的理解?
得分点:
泛型的原因、泛型的概念
标准回答:
泛型是Java语言的一个重要特性,引入于1.5版本。它的主要原因在于在没有泛型之前,从集合中读取对象时需要进行类型转换,这会导致一些问题。如果不小心插入了类型错误的对象,那么在运行时转换处理阶段可能会出现错误。通过引入泛型,我们可以告诉编译器集合应该接受哪种类型的对象。编译器会自动进行插入时的类型转换,并在编译时检查是否插入了类型错误的对象。这使得程序更加安全和清晰。
加分回答:
在泛型中,可以进行向上转型。例如,Java标准库中的ArrayList<T>
实现了List<T>
接口,它可以被向上转型为List<T>
类型。这意味着一个类型为ArrayList<T>
的对象可以被视为List<T>
类型的对象使用。
public class ArrayList<T> implements List<T> {
// ...
}
List<String> list = new ArrayList<String>();
需要注意的是,不能将ArrayList<Integer>
向上转型为ArrayList<Number>
或List<Number>
。这是因为泛型具有类型安全性,编译器会阻止不兼容的类型之间的转型。
为什么不能这样做呢?假设我们可以将ArrayList<Integer>
向上转型为ArrayList<Number>
,然后观察以下代码:
// 创建ArrayList<Integer>类型:
ArrayList<Integer> integerList = new ArrayList<Integer>();
// 添加一个Integer:
integerList.add(new Integer(123));
// “向上转型”为ArrayList<Number>:
ArrayList<Number> numberList = integerList;
// 添加一个Float,因为Float也是Number的子类:
numberList.add(new Float(12.34));
// 从ArrayList<Integer>获取索引为1的元素(即添加的Float):
Integer n = integerList.get(1); // ClassCastException!
在这个示例中,我们试图将一个ArrayList<Integer>
转型为ArrayList<Number>
,这个ArrayList<Number>
实际上与ArrayList<Integer>
是同一个对象,但它被认为是ArrayList<Number>
类型。因此,可以向其中添加Float
类型的元素,然后在获取元素时会导致ClassCastException
异常。为了避免这种类型错误,编译器不允许将ArrayList<Integer>
向上转型为ArrayList<Number>
。