关于泛型的一点理解

这里主要针对一些容易混淆的点:


泛型方法:

为了在静态(static)方法中使用泛型类的类型参数(“T”),于是有了泛型方法,注意泛型方法的格式,类型参数<T>需要放在函数返回值之前。

static <T> void fromArrayToCollection(T[] a, Collection<T>c){


边界通配符:

通配符解决使用(注意,这里是使用)现有泛型容器(类)时无法事先确定类型的情况。

由于泛型的不可协变的特性,导致

List<Object> list = new ArrayList<String>();这样的语句是不能通过编译的。(泛型的不可协变性是为了类型安全考虑的,如果List<Object>可以引用new ArrayList<String>()那么势必在List<Object>中也可以添加Integer对象,最后导致一个ArrayList<String>中存放了Integer对象,造成类型安全问题

于是我们需要借助边界通配符来解决这个问题,List<? extends Object> oList =new ArrayList<String>();这样就可以通过编译了。


另外,在泛型方法的入参里也经常会用到通配符。

public void testMethod1(List<?extends T> param) {}

表示接受一个以T或者T的子类为类型参数的List变量。

这里有一个局限,就是这样声明的param不能进行添加(add)操作,因为“?”表示一个不确定的类型,所以它不能接受任何类型的元素,不过null元素是个例外。


public void testMethod2(List<?super T> param){}

表示接受一个以T或者是T的父类为类型参数的List变量。

这里你就可以向param其中添加T或者T的父类的实例。不过这个方法中你调用param.get()方法获取其中的对象得到的将永远是Object类型


一句话总结:

如果你想从一个数据类型里获取数据,使用 ? extends 通配符

如果你想把对象写入一个数据结构里,使用 ? super 通配符

如果你既想存,又想取,那就别用通配符。




类型擦除:

类型擦除指的是通过类型参数合并,将泛型类型实例关联到同一份字节码上。编译器只为泛型类型生成一份字节码,并将其实例关联到这份字节码上,因此泛型类型中的静态变量是所有实例共享的。

此外,需要注意的是,一个static方法,无法访问泛型类的类型参数,因为类还没有实例化,所以,若static方法需要使用泛型能力,必须使其成为泛型方法。

类型擦除的关键在于从泛型类型中清除类型参数的相关信息,并且再必要的时候添加类型检查和类型转换的方法在使用泛型时,任何具体的类型都被擦除,唯一知道的是你在使用一个对象。比如:List<String>List<Integer>在运行事实上是相同的类型。他们都被擦除成他们的原生类型,即List

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值