java 反射泛型方法_泛型与反射的使用总结之反射篇

前一篇对泛型进行了一番总结,本篇就来说说与泛型有关的反射。我在泛型篇中说到了泛型在JVM中是会被擦除的,不过擦除的类还是“残留”了一些泛型的痕迹。比如Person类,虽然擦除掉了泛型,但是通过反射机制是可以获得这些信息的,不光如此,Person类里面定义的泛型方法都可以通过反射获得。让我们用代码来验证一下。在用代码验证之前,大象会对Person类稍微改造一下,增加一个泛型变量K以及一个泛型方法,其它的都保持不变。publicclassPerson &

Serializable>extendsSuperPersonimplementsHandle {......publicstatic> T max(List<?extendsT> list){Iterator<?extendsT> it =

list.iterator();T result = it.next();while(it.hasNext()){T t = it.next();if(t.compareTo(result)

> 0)result = t;}returnresult;}......}

下面可以开始写代码了吗?别急,大象还想先把代码中用到的几个跟反射有关的API接口说明一下,这都是JDK5.0中为泛型新增的,然后还用到了一个JDK6.0提供的Modifier,它是一个枚举类型,可以表示类、方法或字段的修饰符。Type

它是所有类型的公共接口。包括原始类型、参数化类型、数组类型、类型变量和基本类型。ParameterizedType, TypeVariable, WildcardType,GenericArrayType这四个接口都是它的子接口。

GenericDeclaration

这个接口Class、Method、Constructor都有实现,我们就是要用这个接口的getTypeParameters方法,它返回一个TypeVariable[]数组,这个数组里面就是我们定义的类型变量T和K,顺序与我们声明时一样。如果用循环语句将数组打印出来,你会发现只会输出T和K,这可不是我们想要的结果,那么想要获得预期的结果怎么办呢?请继续往下看。

TypeVariable

它表示类型变量。比如T,比如KextendsComparable<?superT> & Serializable,这个接口里面有个getBounds()方法,它用来获得类型变量上限的Type数组,如果没有定义上限,则默认设定上限为Object,请注意TypeVariable是接口,实际得到的是TypeVariableImpl实现类,下面几个接口都一样。拿T和K来说明,T没有定义任何上限,所以它就有一个默认上限java.lang.Object,实际跟踪代码的时候你会发现T的bounds属性为空,只有在调用了getBounds()方法后,才会有一个Type[1]数组[class java.lang.Object]。而对于K来说,调用了getBounds方法后,得到的数组是[java.lang.Comparable super T>, interface java.io.Serializable],它们的类型却是不一样的,第1个是ParameterizedType,而第二个是Class

ParameterizedType

ParameterizedType表示参数化类型,就是上面说的java.lang.Comparable super T>,再比如List,List,这些都叫参数化类型。得到Comparable super T>之后,再调用getRawType()与getActualTypeArguments()两个方法,就可以得到声明此参数化类型的类(java.lang.Comparable)和实际的类型参数数组([? super T]),而这个? super T又是一个WildcardType类型。

WildcardType它用来描述通配符表达式,上面返回的? super T正好是这个类型。然后调用getUpperBounds()上限和getLowerBounds()下限这两个方法,获得类型变量?的限定类型(上下限),对于本例的通配符(?),它的上限为java.lang.Object,下限为T

通过上面几个接口的分析,可以将Person类的泛型参数都解析出来,那么Person的超类以及实现的接口该怎么处理呢?Class类里面同样在1.5版本加入了getGenericSuperclass()与getGenericInterfaces()两个方法,用于返回带参数化类型的超类与接口。

至此,通过上面这些接口和方法我们已经可以把class Person后面的代码都解析出来了,类里面的方法与解析类的泛型化参数类似,就不再赘述了。下图就是通过反射将定义的Person类打印出来的结果。

b1c6a9e3bbae6b4a0e6358b126f7f196.png

本文主要是想通过反射机制来验证在JVM虚拟机中获得泛型的一些知识。一般实际使用的时候多数是通过反射获取超类的泛型,或者通过反射调用方法,读取/设置属性值等等这些功能,最下面有示例源码的下载。反射虽然很有用处,但也不能滥用。首先用了反射就没办法在编译时进行类型检查,而且反射的代码比较复杂不容易阅读,不过好在现在有很多已经封装好的反射工具类,帮我们做了不少这方面的工作。最后也是最重要的一点是因为,使用反射会有一定的性能损耗,就是说会比直接调用方法要慢,至于慢多少,这个不好说,但肯定会慢,因此除非有必要,大象建议在一般情况下首先考虑用接口来代替反射。

以上这些都是本篇关于泛型相关的反射介绍,算是一个入门知识吧,有什么不对的,或不完善的地方,还请各位指出来,谢谢!源码下载:本文为菠萝大象原创,如要转载请注明出处。

posted on 2014-05-06 14:33 菠萝大象 阅读(5728) 评论(1)  编辑  收藏 所属分类: Java

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值