java泛型原理(泛型擦除)

java泛型原理(泛型擦除)

Java的泛型是伪泛型,因为在编译期间,所有的泛型信息都会被擦除掉,我们常称为泛型擦除.

java的泛型是由编译期这个层次实现的,字节码是不包含泛型中的类型信息的。

可以证明发生类型擦除的例子

public static void main(String[] args) throws IOException, ClassNotFoundException {
        List<String> integerList = new ArrayList<>();
        List<Integer> floatList = new ArrayList<>();
        System.out.println(integerList.getClass() == floatList.getClass());
    }
//通过反射可以绕过泛型类型限定
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        List<Integer> integerList = new ArrayList<>();
        integerList.add(new Integer(11));
        Class<? extends List> aClass = integerList.getClass();
        Method add = aClass.getMethod("add", Object.class);
        add.invoke(integerList,"1111");
        for (Object e:integerList){
            System.out.println(e);
        }
    }

类型擦除之后保存的是原始类型

原始类型就是擦除了泛型信息,最后在字节码中的类型变量的真正类型。无论何时定义一个泛型类型,相应的原始类型都会被自动地提供。类型变量被擦除,并使用其限定类型(无限定的变量用Object替换)。

如果泛型的定义是 擦除之后就是Object。

如果泛型定义是<T extends Collection & List>哪个在前就是哪个。现在是Collection

泛型方法的调用

在调用泛型方法时可以不指定泛型。在不指定泛型的情况下,泛型变量的类型为该方法中的几种类型的同一个父类的最小级,直到Object。在指定泛型的时候,该方法中的几种类型必须是该泛型实例类型或者其子类。

class Test {
    public static void main(String[] args) {
        //不指定泛型的时候
        int a1 = add(1, 2); /
        Number b1 = add(1, 1.2);
        Object c1 = add(1, "my");

        //指定泛型的时候
        int a = Test.<Integer>add(1, 2);//指定了Integer,所以只能为Integer类型或者其子类
//        int b = Test.<Integer>add(1, 2.2);//编译错误,指定了Integer,不能为Float
        Number c = Test.<Number>add(1, 2.2); //指定为Number,所以可以为Integer和Float
    }

    public static <T> T add(T x, T y) {
        return x;
    }
}

泛型的类型检测针对谁?

public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<String>();
        arrayList.add(1); //编译报错

        ArrayList<String> arrayList1 = new ArrayList(); //第一种 情况
        arrayList1.add(1); //编译报错

        ArrayList arrayList2 = new ArrayList<String>();//第二种 情况
        arrayList2.add(1);
    }

​ 类型检查就是针对引用,谁是一个引用,用这个引用调用泛型方法,就会对这个引用调用方法进行类型检查,而无关它真正引用的对象。

类型转换

当一个具有擦除返回类型的泛型方法被调用时会进行强制类型转换。

在调用这个返回一个泛型的地方会根据类型变量进行强转(做了一个checkcast()操作,即检查< String >中的类型并强转)

类型擦除和多态的冲突解决办法

JVM采用桥方法来完成这项功能。

父类在进行类型擦除之后会变成原始数据类型。编译器会自动生成桥方法,桥方法的参数类型都是Object,桥方法的内部实现就是调用子类实现的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值