1. Java中的泛型是什么 ? 使用泛型的好处是什么?
    它提供了编译期的类型安全,确保你只能把正确类型的对象放入集合中,避免了在运行时出现ClassCastException。

    一个被举了无数次的例子:

    1. List arrayList = new ArrayList();
    2. arrayList.add("aaaa");
    3. arrayList.add(100);
    4. for(int i = 0; i< arrayList.size();i++){
    5. String item = (String)arrayList.get(i);
    6. Log.d("泛型测试","item = " + item);
    7. }

    毫无疑问,程序的运行结果会以崩溃结束:

    java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

    我们将第一行声明初始化list的代码更改一下,编译器会在编译阶段就能够帮我们发现类似这样的问题。

    1. List<String> arrayList = new ArrayList<String>();
    2. ...
    3. //arrayList.add(100); 在编译阶段,编译器就会报错

    2. Java的泛型是如何工作的 ? 什么是类型擦除 ?
    泛型是通过类型擦除来实现的,编译器在编译时擦除了所有类型相关的信息,所以在运行时不存在任何类型相关的信息。

    1. public class Main{
    2. pub1ic static void main(string[] args) {
    3. ArrayList<Integer> arrayList1 = new ArrayList<>();
    4. ArrayList<String> arrayList2 = new ArrayList<>();
    5. System.out.println(arrayList1.getclass() == arrayList2.getc1ass());
    6. }
    7. }

    输出结果:

    true

    可以看到ArrayList和ArrayList的原始类型是相同,在编译成字节码文件后都会变成List,JVM看到的只有List),看不到泛型信息,这就是泛型的类型擦除。在看下面这段代码。

    1. public class Main{
    2. public static void main(String[] args) throws Exception{
    3. ArrayList<Integer> arrayList =new ArrayList<>();
    4. arrayList.add(1);
    5. arrayList.getClass().getMethod("add",Object.class).invoke(arrayList,"a")
    6. System.out.prinltn(arrayList.get(0));
    7. System.out.prinltn(arrayList.get(1));

    输出

    1 a

    可以看到通过反射进行add操作,ArrayList竟然可以存储字符串,这是因为在反射就是在运行期调 用的add方法,在运行期泛型信息已经被擦除。

    • 既然存在类型擦除,那么Java是如何保证在ArrayList添加字符串会报错呢?Java编译器是通过先检查代码中泛型的类型,然后在进行类型擦除,再进行编译。

    3.什么是泛型中的限定通配符和非限定通配符 ?
    限定通配符对类型进行了限制。有两种限定通配符,一种是<? extends T> 上限通配符 适合读 另一种是<? super T> 下限通配符 适合插
    非限定通配符可以用任何类型来限定。

    上限通配符:必修是T或者T的子类 下限通配符:必须是T或者T的父类。