泛型的擦除

实际上,从虚拟机的角度看,不存在泛型概念。

        泛型是运用在编译时期的技术:编译时编译器会按照<类型名>的类型对容器中的元素进行检查,检查不匹配,就编译失败。如果全部检查成功,则编译通过,但编译通过后产生的 .class文件中还有<类型名>这个标识,即字节码的类文件中有泛型,但是运行时并没有泛型这就是泛型的擦除。

        可以通过使用javap反编译查看字节码文件,可以看到其中包含泛型

一句话总结就是:在.java文件运用泛型技术时,编译器在文件编译通过后运行时自动擦除泛型标识。

如果需要使用泛型的类型,则需要通过反射机制进行保存

abstract class A1<TF> {
      private Class<TF> clz; // 就是T的具体类型
      // 在构造器中获取T的具体类型
      public A1() {
                ParameterizedType c = (ParameterizedType) this.getClass().getGenericSuperclass(); // 获取到父类型的定义com.yan6.A1<T>
                clz=(Class)(c.getActualTypeArguments()[0]);  //获取真实的类型参数  T

        }
}

由于泛型的擦除,运行时并没有泛型机制,同时也没有使用向下类型转换,那么为何运行时无异常?

这是由于泛型的补偿

List<String> list=new ArrayList<>();

for(String tmp:list) System.out.println(tmp.length());  //泛型的补偿

编译器在擦除泛型后,会自动将类型转换为原定义的泛型,这样就不必再做向下类型转换了。

for(Object tmp:list){
       if(tmp instanceof String){
           System.out.println(((String)tmp).length());
       }
}

泛型的擦除和补偿这两个机制都是编译器内部自动完成的。

可以通过反射获取类型参数

泛型的局限性

        - 不能使用基本类型
        - 不能使用泛型类异常
        - 不能使用泛型数组

不能实例化参数类型对象。例如T ob = new T();

import java.lang.reflect.ParameterizedType;

public class Test1 {
	public static void main(String[] args) throws Exception {
		B1 bb=new B1();
		System.out.println("dd:"+bb.getTt());
	}
}

abstract class A1<TF>{
	private Class<TF> clz;  //就是T的具体类型
	private TF tt;
	
	//在构造器中获取T的具体类型
	public A1() throws Exception {
		ParameterizedType c=(ParameterizedType)this.getClass().getGenericSuperclass();  //获取到父类型的定义  com.yan6.A1<T>
		clz=(Class)(c.getActualTypeArguments()[0]);   //获取真实的类型参数  T
		tt=clz.newInstance();
		System.out.println(c.getActualTypeArguments()[0]);  //class java.lang.String
//		Class c=this.getClass(); //class com.yan6.B1
//		System.out.println(c);
	}
	public Class getParent() {
		return this.clz;
	}
	public TF getTt() {
		return tt;
	}
	public void setTt(TF tt) {
		this.tt = tt;
	}
}

class B1 extends A1<String>{
	public B1() throws Exception {
		super();
	}
}
import java.lang.reflect.Method;

public class Test2 {
	public static void main(String[] args) throws Exception {
		String clz="java.util.Date";
		System.out.println(Class.forName(clz).newInstance());
		
		A2 aa=new A2();
//		aa.pp();
		
		Method method=aa.getClass().getDeclaredMethod("pp");
		method.setAccessible(true);
		Object res=method.invoke(aa);
		System.out.println(res);
	}
}

class A2{
	private String pp() {
		return "neimengren";
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值