原文地址:http://tutorials.jenkov.com/java-reflection/generics.html

========================================================================================

我经常在一些文章和论坛中看有人说Java泛型信息都会在编译时被擦除,所以你不能在运行时访问任何相关的信息。这也不完全对。在运行时,在少数情况下也是可以访问到泛型信息的。实际上,这些情况中已经满足了我们对Java泛型信息的需求。本文将解释这几种情况。
     下面是本文所涵盖的主题列表:

  1. The Generics Reflection Rule of Thumb ()
  2. Generic Method Return Type (方法返回值类型的泛型)
  3. Generic Method Parameter Types (方法参数类型的泛型)
  4. Generic Field Types (字段类型的泛型)

========================================================================================

  • The Generics Reflection Rule of Thumb

使用Java泛型无外乎就下面两种情况中的一种:

  1. Declaring a class/interface as being parameterizable. (声明类、接口参数化)
  2. Using a parameterizable class.(使用参数化的类)

当你写一个类或者接口的时候,你可以指定它可以被参数化。java.util.List接口就是这种用法。你可以使java.util.List参数化的创建一个String的列表,而不是创建一个Object的列表。
     当在运行时检查参数化类型它自己的类型时,如java.util.List,没有办法知道它具体被参数化成了什么类型。这样也合理,因为在同一应用程序中参数化的类型可以是所有类型。但是,当你检查用参数化类型声明的方法或者字段时,你可以知道它们在运行时参数化成了什么类型。简而言之:
     在运行时,你不会知道参数化类型它自己的类型,但是你能知道用了参数化类型的字段和方法的类型。换句话说,它们有具体的参数类型。
     下面的部分我们将更进一步的来看这几种情况。
========================================================================================

  • Generic Method Return Types

如果你获得了java.lang.reflect.Method对象,你也是有可能获得它的返回值类型的泛型信息的。这不会是任何参数化类型的Method对象,除了在类里面使用了参数化类型。你可以去看“Java泛型:方法”来了解如何获取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[ ]类型的数组typeArguements中包含一个项——一个代表实现了Type接口的java.lang.String.Class的Class实例。

========================================================================================

  • Generic Method Parameter Types

在运行时,你也可以用Java反射机制访问泛型参数的类型。下面是一个例子,类里面有一个参数化类型的参数:

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中包含一个项——一个代表实现了Type接口的java.lang.String.Class的Class实例。

========================================================================================

  • Generic Field Types

也可以访问公有字段的泛型类型。字段是类的成员变量——要么是静态变量,要么是实体变量。你可以去看“Java泛型:字段”来了解如何获取Field对象。下面是一个很早之前的例子,类中有有一个叫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数组中包含一个项——一个代表实现了Type接口的java.lang.String.Class的Class实例。

========================================================================================

  • 目录

  这是一个本教程到目前为止涵盖的主题列表:

  1. Java反射——引言
  2. Java反射——Class对象
  3. Java反射——构造函数
  4. Java反射——字段
  5. Java反射——方法
  6. Java反射——Getter和Setter
  7. Java反射——私有字段和私有方法
  8. Java反射——注解
  9. Java反射——泛型
  10. Java反射——数组
  11. Java反射——动态代理
  12. Java反射——类的动态加载和重新加载

(敬请期待下一篇翻译)

【译】9. Java反射——泛型的更多相关文章

  1. 【译】1. Java反射——引言

    原文地址:http://tutorials.jenkov.com/java-reflection/index.html *By Jakob Jenkov Java的反射机制使得它可以在运行时检查类.接 ...

  2. 【译】2. Java反射——Class对象

    原文地址:http://tutorials.jenkov.com/java-reflection/classes.html ====================================== ...

  3. 【译】3. Java反射——构造函数

    原文地址:http://tutorials.jenkov.com/java-reflection/constructors.html ================================= ...

  4. 【译】4. Java反射——字段

    原文地址:http://tutorials.jenkov.com/java-reflection/fields.html ======================================= ...

  5. 【译】5. Java反射——方法

    原文地址:http://tutorials.jenkov.com/java-reflection/methods.html ====================================== ...

  6. 【译】6. Java反射——Getter和Setter

    原文地址:http://tutorials.jenkov.com/java-reflection/getters-setters.html ============================== ...

  7. 【译】7. Java反射——私有字段和私有方法

    原文地址:http://tutorials.jenkov.com/java-reflection/private-fields-and-methods.html =================== ...

  8. 【译】8. Java反射——注解

    原文地址:http://tutorials.jenkov.com/java-reflection/annotations.html ================================== ...

  9. 【译】10. Java反射——数组

    原文地址:http://tutorials.jenkov.com/java-reflection/arrays.html ======================================= ...

随机推荐

  1. python学习笔记(11)--文件与数据格式化

    文件的概念: 文件是数据的抽象和集合,是存储在辅助存储器上的数据序列,文件是数据存储的一种形式,文件的展现形态,文本文件和二进制文件. 文本文件输出: f.txt文件保存:“我是中国人” >&g ...

  2. static关键字的用法

    静态变量和静态方法 static关键字的基本用法: 1.修饰变量:被static修饰的变量属于类变量,可以用类名.变量名来引用,而不用直接new一个对象来引用. 2.修饰方法:被static修饰的方法 ...

  3. $mount(“#app”)手动挂载

    没有el属性时,证明vue还没绑定到特定的dom上,需要延迟加载,则使用.$mount("")进行手动挂载 https://blog.csdn.net/longzhoufeng/a ...

  4. 关于PHP函数传参的注意点

    PHP的实参在传递过程中是顺序传递的,不支持指定参数名传递.怎么理解呢?看下面的代码: function test($name,$age){ echo '姓名:'.$name,' 年纪:'.$age; ...

  5. How to install rime on Debian

    apt-get install ibus ibus-rime librime-data-wubi reboot cp ~/.config/ibus/rime/default.yaml ~/.confi ...

  6. bzoj-1191(二分图最大匹配)

    解题思路:比较裸的一道题,直接跑匈牙利就行了,但是要注意一点,这个兔崽子是在闯关,一道题回答不出来就没了,直接在题目循环那里加一个else break;就行了!!!; #include<iost ...

  7. Nginx TSL/SSL优化握手性能

    L:131

  8. 【深入Java虚拟机】之一:Java内存模型

    [深入Java虚拟机]之:Java内存区域与内存溢出 内存区域 Java虚拟机在执行Java程序的过程中会把他所管理的内存划分为若干个不同的数据区域.Java虚拟机规范将JVM所管理的内存分为以下几个 ...

  9. Redis宕机的问题

    在主从模式下宕机要分为区分来看: slave从redis宕机 ​ 在Redis中从库重新启动后会自动加入到主从架构中,自动完成同步数据: ​ 如果从数据库实现了持久化,只要重新假如到主从架构中会实现增 ...

  10. H.264编码原理以及I帧B帧P帧

    前言 ----------------------- H264是新一代的编码标准,以高压缩高质量和支持多种网络的流媒体传输著称,在编码方面,我理解的他的理论依据是:参照一段时间内图像的统计结果表明,在 ...