脚本宝典收集整理的这篇文章主要介绍了

Java反射-范型

脚本宝典小编觉得挺不错的,现在分享给大家,也给大家做个参考,希望能帮助你少写一行代码,多一份安全和惬意。

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

范型反射的使用法则

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

  1. 定义一个可参数化的类/接口
  2. 使用可参数化的类

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

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

当使用反射检视可参数化类型本身时,比如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<String> stringList = ...;    public List<String> getStringList(){     return this.stringList;   } }

在这个类中可以获得方法getStringList()的带范型的返回类型。换言之,可以发现方法getStringList()返回List<String>并不仅仅是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<String> stringList = ...;    public void setStringList(List<String> 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.StringClass实例。Class实现了Type`接口。

属性是范型类型

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

public class MyClass {   public List<String> 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接口。

总结

以上是脚本宝典为你收集整理的

Java反射-范型

全部内容,希望文章能够帮你解决

Java反射-范型

所遇到的程序开发问题,欢迎加入QQ群277859234一起讨论学习。如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典网站推荐给程序员好友。 本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。

80%的人都看过