运用泛型反射的经验法则

使用场景

  1. 声明一个需要被参数化(parameterizable)的类/接口。
  2. 使用一个参数化类。

当你声明一个类或者接口的时候你可以指明这个类或接口可以被参数化, java.util.List 接口就是典型的例子。你可以运用泛型机制创建一个标明存储的是 String 类型 list,这样比你创建一个 Object 的list 要更好。
当你想在运行期参数化类型本身,比如你想检查 java.util.List 类的参数化类型,你是没有办法能知道他具体的参数化类型是什么。
不能在运行期获知一个被参数化的类型的具体参数类型是什么,但是你可以在用到这个被参数化类型的方法以及变量中找到他们,换句话说就是获知他们具体的参数化类型。

泛型方法返回类型

  1. public class MyClass {
  2. protected List<String> stringList = ...;
  3. public List<String> getStringList(){
  4. return this.stringList;
  5. }
  6. }

我们可以获取 getStringList() 方法的泛型返回类型,换句话说,我们可以检测到 getStringList() 方法返回的是 List 而不仅仅只是一个 List。如下例:

  1. Method method = MyClass.class.getMethod("getStringList", null);
  2. Type returnType = method.getGenericReturnType();
  3. if (returnType instanceof ParameterizedType) {
  4. ParameterizedType type = (ParameterizedType) returnType;
  5. Type[] typeArguments = type.getActualTypeArguments();
  6. for(Type typeArgument : typeArguments){
  7. Class typeArgClass = (Class) typeArgument;
  8. System.out.println("typeArgClass = " + typeArgClass);
  9. }
  10. }

这段代码会打印出 “typeArgClass = java.lang.String”,Type[] 数组 typeArguments 只有一个结果 – 一个代表 java.lang.String 的 Class 类的实例。Class 类实现了 Type 接口。

泛型方法参数类型

你同样可以通过反射来获取方法参数的泛型类型,下面这个例子定义了一个类,这个类中的方法的参数是一个被参数化的 List:

  1. public class MyClass {
  2. protected List<String> stringList = ...;
  3. public void setStringList(List<String> list){
  4. this.stringList = list;
  5. }
  6. }

可以像这样来获取方法的泛型参数:

  1. method = Myclass.class.getMethod("setStringList", List.class);
  2. Type[] genericParameterTypes = method.getGenericParameterTypes();
  3. for (Type genericParameterType : genericParameterTypes) {
  4. if (genericParameterType instanceof ParameterizedType) {
  5. ParameterizedType aType = (ParameterizedType) genericParameterType;
  6. Type[] parameterArgTypes = aType.getActualTypeArguments();
  7. for (Type parameterArgType : parameterArgTypes) {
  8. Class parameterArgClass = (Class) parameterArgType;
  9. System.out.println("parameterArgClass = " + parameterArgClass);
  10. }
  11. }
  12. }

这段代码会打印出”parameterArgType = java.lang.String”。Type[]数组 parameterArgTypes 只有一个结果 – 一个代表 java.lang.String 的 Class 类的实例。Class 类实现了Type接口。

泛型变量类型

  1. public class MyClass {
  2. public List<String> stringList = ...;
  3. }
  4. Field field = MyClass.class.getField("stringList");
  5. Type genericFieldType = field.getGenericType();
  6. if(genericFieldType instanceof ParameterizedType){
  7. ParameterizedType aType = (ParameterizedType) genericFieldType;
  8. Type[] fieldArgTypes = aType.getActualTypeArguments();
  9. for(Type fieldArgType : fieldArgTypes){
  10. Class fieldArgClass = (Class) fieldArgType;
  11. System.out.println("fieldArgClass = " + fieldArgClass);
  12. }
  13. }

这段代码会打印出”fieldArgClass = java.lang.String”。Type[] 数组 fieldArgClass 只有一个结果 – 一个代表 java.lang.String 的 Class 类的实例。Class 类实现了 Type 接口。