原文地址: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. Golang的面向对象实践method

    最近在系统的学习go的语法,一切都弄好了之后准备弄个im项目出来玩.在这个过程中会把看到有趣的写法和语法啥的拿出来分析一下. 我一直以为go语言对面向对象没有支持,但是后面看到了类似类的概念,meth ...

  2. scrapy架构简介

    一.scrapy架构介绍 1.结构简图: 主要组成部分:Spider(产出request,处理response),Pipeline,Downloader,Scheduler,Scrapy Engine ...

  3. SCP传送文件时提示No ECDSA host key is known forx.x.x.x and you have requested strict checking.问题的解决办法

    在使用SCP向其他设备传送文件时,打印如下错误: No ECDSA host key is known for x.x.x.x and you have requested strict checki ...

  4. 待解决ava.lang.OutOfMemoryError: PermGen space at java.lang.ClassLoader.defineClass1(Native Method)

    java.lang.OutOfMemoryError: PermGen space at java.lang.ClassLoader.defineClass1(Native Method) at ja ...

  5. Real-time chart using ASP.NET Core and WebSocket

    Solution in glance The following diagram illustrates our solution where IoT device reports readings ...

  6. default配置页面一级菜单用于进入二级菜单

  7. Nginx 热部署最版本

    L10 进入nginx里的sbin目录 拷贝原先的做备份 cp nginx nginx.old 然后将已经编译好的nginx二进制文件复制到sbin目录下并覆盖原有的二进制文件 kill -USR2 ...

  8. Eclipse环境配置与快捷命令

    1.VS.Chrome.Eclipse调试命令对比: VS: F5: 继续运行 F10: 单步执行 F11: 进入函数内部 Shift + F11: 由函数内部返回调用处 Chrome: F8: 继续 ...

  9. HDU 4256 翻译罗马数字

    参考自:https://www.cnblogs.com/ECJTUACM-873284962/p/6414173.html The Famous Clock Time Limit: 2000/1000 ...

  10. Dirichlet's Theorem on Arithmetic Progressions POJ - 3006 线性欧拉筛

    题意 给出a d n    给出数列 a,a+d,a+2d,a+3d......a+kd 问第n个数是几 保证答案不溢出 直接线性筛模拟即可 #include<cstdio> #inclu ...