在Java中是否可以通过反射找出集合getter的泛型类型?

时间:2014-09-09 09:00:47

标签: java reflection

我有一个带有集合吸气剂的课程,我通过反思进行检查。像这样:

class Bar {
  String baz;
  int bazooka;
}
class Foo {
  List<Bar> bars = new ArrayList<Bar>();
  List<Bar> getBarsList() { return bars; }
}

我需要在运行时找到的是类对象Class<Bar>。我知道如果您引用Field对象,则可能。但是它也可能来自getter Method

2 个答案:

答案 0 :(得分:4)

在您的情况下,可以使用反射。您不能做的是获取有关类型的运行时信息。给定一个参数化类型的实例,您无法在运行时找出参数化的内容。这是其他答案告诉你的,但这不是你要问的。你问的是编译时类型约束。

public class Test {

  public static void main(String args[]) throws NoSuchMethodException {
    Method method = Foo.class.getDeclaredMethod("getBars", new Class[]{});
    Type grt = method.getGenericReturnType();
    if (grt instanceof ParameterizedType) {
      Type Bar = ((ParameterizedType) grt).getActualTypeArguments()[0];
      System.out.println(Bar);
    }
  }
}

class Foo {
  List<Bar> getBars() {
    return Collections.emptyList();
  }
}

class Bar {
}

打印class com.package.Bar

如果另一方面你有这样的课程:

class Foo<T> {
  List<T> getBars() {
    return Collections.emptyList();
  }
}

然后你无法在运行时获得T的Foo实例。存在变通方法,其中人们创建具有固定类型参数的匿名子类。

答案 1 :(得分:1)

由于两个原因,该信息在运行时不存在:

1)那里不需要它。这是对编译器的暗示,并符合您的强类型方法。

2)Java使用泛型类型擦除来保持与预泛类型的兼容性。

可以但是以另一种方式执行此操作(愚蠢,但如果代码是您的,则可以使用):

class MyGenericClass extends ArrayList<MyObject> {

     // Check the class for this variable name. Its type will indicate the generic type.
     // Alternatively we can use the type class instance directly.
     final static MyObject mGenericType      = null; 
     final static Class    mGenericTypeClass = MyObject.getClass();

} 

我知道这是一个部分解决方案(如果有任何解决方案),但是,如果你真的需要这个,那么总比没有好。

再想一想,有一种简单的方法可以做到这一点。您可以使用参数创建一个可保留的注释,该参数将提供有关注释类/字段的泛型类型的信息。