java范形_Java反射-范型

我经常在文章或论坛中读到所有的Java范型信息都会在编译时搽除,所以不能在运行时访问范型的任何信息。这并不完全准确。某些案例下可以在运行时访问范型信息,这些案例实际上覆盖了我们对范型信息的一些需求。本文将解释这些案例。

范型反射的使用法则

使用范型通常有2种不同的场景:

定义一个可参数化的类/接口

使用可参数化的类

当你编写一个类/接口时,可以指定类/接口是否被参数化。这是java.util.List接口的示例。你可以参数化java.util.List接口去创建一个String类型的list,而不是object list,如下:

List myList = new ArrayList();

当使用反射检视可参数化类型本身时,比如java.util.List,是没有办法得到它的已参数化的类型的。object自身是不知道它参数化的类型的。

然而,object的reference知道它包含的范型引用的类型信息。那就是,如果它不是局部变量。如果一个object被另一个object的field引用,你就可以通过反射查看Field定义,通过field获得范型的类型信息。

同理,如果一个object被一个方法的参数引用。可以通过方法的Parameter,你可以看到方法参数确定范型的类型信息。

最后,你可以通过方法返回值确定反射范型信息。需要强调的是,实际返回object时你不能得到范型信息。你需要通过反射查看方法定义,去获得方法定义的返回值(包含范型信息)。

总结起来就是:你只能通过object的引用查看它的范型信息,而不能通过它自身查看。

下面的部分将仔细研究这些情况。

方法返回范型类型

如你已获得java.lang.reflect.Method对象,那么就可以获得它的返回值的范型。你可以阅读"Java Generics: Methods"学习如何获得Method对象。下面示例类的方法拥有一个可参数化的返回类型。

public class MyClass {

protected List stringList = ...;

public List getStringList(){

return this.stringList;

}

}

在这个类中可以获得方法getStringList()的带范型的返回类型。换言之,可以发现方法getStringList()返回List并不仅仅是List。代码如下:

Method method = MyClass.class.getMethod("getStringList", null);

Type returnType = method.getGenericReturnType();

if(returnType instanceof ParameterizedType){

ParameterizedType type = (ParameterizedType) returnType;

Type[] typeArguments = type.getActualTypeArguments();

for(Type typeArgument : typeArguments){

Class typeArgClass = (Class) typeArgument;

System.out.println("typeArgClass = " + typeArgClass);

}

}

上面的代码块将输出"typeArgClass = java.lang.String"。Type[]数组typeArguments包含单个元素-java.lang.String类的Class实例。Class实现了Type接口。

方法参数是范型类型

你也可以在运行时通过反射访问方法的范型参数。下面示例类有一个方法拥有一个参数化List作为参数:

public class MyClass {

protected List stringList = ...;

public void setStringList(List list){

this.stringList = list;

}

}

可以访问方法参数的范型类型,代码如下:

method = Myclass.class.getMethod("setStringList", List.class);

Type[] genericParameterTypes = method.getGenericParameterTypes();

for(Type genericParameterType : genericParameterTypes){

if(genericParameterType instanceof ParameterizedType){

ParameterizedType aType = (ParameterizedType) genericParameterType;

Type[] parameterArgTypes = aType.getActualTypeArguments();

for(Type parameterArgType : parameterArgTypes){

Class parameterArgClass = (Class) parameterArgType;

System.out.println("parameterArgClass = " + parameterArgClass);

}

}

}

上述代码将输出"parameterArgType = java.lang.String"。数组Type[]`parameterArgTypes包含单个元素-代表类java.lang.String的Class实例。Class实现了Type`接口。

属性是范型类型

同样的,我们也可以访问公共属性的范型类型。属性是类的成员变量-无论静态或实例变量。你可以获得关于Field的文章"Java Generics: Fields",下方是早些时候的示例代码,拥有一个名为stringList的属性:

public class MyClass {

public List stringList = ...;

}

Field field = MyClass.class.getField("stringList");

Type genericFieldType = field.getGenericType();

if(genericFieldType instanceof ParameterizedType){

ParameterizedType aType = (ParameterizedType) genericFieldType;

Type[] fieldArgTypes = aType.getActualTypeArguments();

for(Type fieldArgType : fieldArgTypes){

Class fieldArgClass = (Class) fieldArgType;

System.out.println("fieldArgClass = " + fieldArgClass);

}

}

上面的代码将输出"fieldArgClass = java.lang.String"。Type[]数组fieldArgTypes包含的单元素-代表java.lang.String类的Class实例。Class实现了Type接口。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值