Java泛型进阶

1.泛型类型安全检查

 泛型的生存期为编译阶段,编译后生成字节码形式的Class文件,泛型信息被擦除,专业术语叫做类型擦除。所以在编译阶段,编译器会进行泛型类型安全检查,保证泛型类型匹配。

List<String> list = new ArrayList<>();
list.add("aaa");
list.add(100);//无法编译通过

 因为编译时会进行泛型类型安全检查,上面最后一行代码无法编译通过。
 来看一下add方法的源码:

public class ArrayList<E>{
    public boolean add(E e) {
		//...
    }
}

泛型类型参数E确定为String后,在编译时,上述代码相当于:

public class ArrayList<String>{
    public boolean add(String e) {
		//...
    }
}

 在编译代码list.add(100);时,实参类型与形参类型不匹配,所以无法编译通过。这就是泛型类型安全检查,保证了代码类型匹配时的安全性。

2.泛型类型擦除

 泛型的生存期为编译阶段,编译后生成字节码形式的Class文件,泛型信息被擦除,专业术语叫做类型擦除。
 泛型时java1.5才引入的,因为泛型类型擦除,使得泛型代码能与之前的代码兼容。

List<String>  l1 = new ArrayList<>();
List<Integer> l2 = new ArrayList<>();
System.out.println(l1.getClass() == l2.getClass());

 因为泛型类型擦除,,List<String>List<Integer>在jvm中的Class对象都是List.class;所以上面代码的输出为true。
 泛型转译:<T>中T转译成Object,而类似<T extends String>转译成类型上限。

3.通过反射逃避泛型安全检查

 因为泛型类型擦除的存在,我们可以借助反射的手段逃避泛型安全检查,使得第一节中往List中加入Integer类型元素能实现。

/*
 * 通过反射逃避泛型检查
 * 例如:有一个String泛型的List,怎样能向这个List中添加一个Integer类型的值?
 */
public class Demo {
	public static void main(String[] args) throws Exception{
		ArrayList<String> strList = new ArrayList<>();
		strList.add("aaa");
		strList.add("bbb");
		
	//	strList.add(100);//无法编译通过,因为泛型类型检查
		//获取ArrayList的Class对象,反向调用add()方法,添加元素
		Class listClass = strList.getClass(); //得到 strList 对象的字节码 对象
		//获取add()方法
		Method m = listClass.getMethod("add", Object.class);
		//调用add()方法
		m.invoke(strList, 100);
		
		//遍历集合
		for(Object obj : strList){
			System.out.println(obj);
		}
	}

运行结果:

aaa
bbb
100

参考博客:https://blog.youkuaiyun.com/briblue/article/details/76736356

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值