1. Java中的泛型是什么 ? 使用泛型的好处是什么?
它提供了编译期的类型安全,确保你只能把正确类型的对象放入集合中,避免了在运行时出现ClassCastException。
一个被举了无数次的例子:
List arrayList = new ArrayList();
arrayList.add("aaaa");
arrayList.add(100);
for(int i = 0; i< arrayList.size();i++){
String item = (String)arrayList.get(i);
Log.d("泛型测试","item = " + item);
}
毫无疑问,程序的运行结果会以崩溃结束:
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
我们将第一行声明初始化list的代码更改一下,编译器会在编译阶段就能够帮我们发现类似这样的问题。
List<String> arrayList = new ArrayList<String>();
...
//arrayList.add(100); 在编译阶段,编译器就会报错
2. Java的泛型是如何工作的 ? 什么是类型擦除 ?
泛型是通过类型擦除来实现的,编译器在编译时擦除了所有类型相关的信息,所以在运行时不存在任何类型相关的信息。
public class Main{
pub1ic static void main(string[] args) {
ArrayList<Integer> arrayList1 = new ArrayList<>();
ArrayList<String> arrayList2 = new ArrayList<>();
System.out.println(arrayList1.getclass() == arrayList2.getc1ass());
}
}
输出结果:
true
可以看到ArrayList
public class Main{
public static void main(String[] args) throws Exception{
ArrayList<Integer> arrayList =new ArrayList<>();
arrayList.add(1);
arrayList.getClass().getMethod("add",Object.class).invoke(arrayList,"a")
System.out.prinltn(arrayList.get(0));
System.out.prinltn(arrayList.get(1));
输出
1 a
可以看到通过反射进行add操作,ArrayList
- 既然存在类型擦除,那么Java是如何保证在ArrayList
添加字符串会报错呢?Java编译器是通过先检查代码中泛型的类型,然后在进行类型擦除,再进行编译。
3.什么是泛型中的限定通配符和非限定通配符 ?
限定通配符对类型进行了限制。有两种限定通配符,一种是<? extends T> 上限通配符 适合读 另一种是<? super T> 下限通配符 适合插
非限定通配符可以用任何类型来限定。
上限通配符:必修是T或者T的子类 下限通配符:必须是T或者T的父类。