使用反射获取字段的通用类型

3

有没有一种方法可以在Java中获取字段的通用类型?

我有以下对象变量:

protected ScheduleView<WantedClass> scheduleLine1;
protected ScheduleView<SomeOtherClass> scheduleLine2;

现在我尝试使用反射技术来获取所有变量类型为ScheduleView,并且通用类型为WantedClass的对象变量:

Arrays.asList(this.getClass().getDeclaredFields()).stream().map(field -> {
    ScheduleView<WantedClass> retValue = null;

    System.out.println(field.getGenericType()); // prints control.ScheduleView<dto.WantedClass>

    try {
        if (field.getType() == ScheduleView.class) { // here I also want to check if the generic type is WantedClass
            retValue = (ScheduleView<WantedClass>) field.get(this);
        } else {
            retValue = null;
        }
    } catch (IllegalAccessException e) {
        retValue = null;
    } finally {
        return retValue;
    }
}).filter(scheduleView -> scheduleView != null).forEach(scheduleView -> {
        /* some more code */
});

问题是我还想在if语句中检查泛型类型是否为WantedClass。我也尝试使用getGenericType()方法,但似乎这样做不可能:

field.getGenericType() == ScheduleView<WantedClass>.class

那么是否有一种方法可以获得字段的通用类型?


不行,那些在编译时被擦除了。你无法检索到那种类型。 - f1sh
2
@f1sh 你确定吗?这些不是类型变量(我猜)。 - Andy Turner
2
@f1sh 如果所有通用类型都在编译时被擦除,为什么 System.out.println(field.getGenericType()); 会打印出 control.ScheduleView<dto.WantedClass> - Michael Langhammer
我错了,你是正确的。 - f1sh
2个回答

4

您需要检查字段是否为ParameterizedType,然后检查getActualTypeArguments的内容,例如:

    for (Field field : Ideone.class.getDeclaredFields()) {
        Type type = field.getGenericType();
        if (type instanceof ParameterizedType) {
            ParameterizedType ptype = (ParameterizedType) type;
            if (ptype.getRawType() == ScheduledView.class) {
                if (ptype.getActualTypeArguments().length == 1
                    && ptype.getActualTypeArguments()[0] == WantedClass.class) {
                  // Do whatever with the field.
                  System.out.println(field.getName());
                }
            }
        }
    }

Ideone demo


2

使用流实现@Andy Turner的答案:

// For each declared field in the class...
Arrays.stream(Ideone.class.getDeclaredFields())
  // select fields...
  .filter(
    // that have a generic type...
    field -> Stream.of(field.getGenericType())
      // that is an instance of ParametrizedType...
      .filter(ParameterizedType.class::isInstance)
      .map(ParameterizedType.class::cast)
      // whose raw type is ScheduledView...
      .filter(ptype -> ptype.getRawType().equals(ScheduledView.class))
      // and whose actual type arguments...
      .map(ParameterizedType::getActualTypeArguments)
      .flatMap(Arrays::stream)
      // include WantedClass...
      .anyMatch(WantedClass.class::equals)
  )
  // then get their names...
  .map(Field::getName)
  // and print them.
  .forEach(System.out::println)
;

@Holger 流使用现在已经被去夸张化。 - srborlongan
@Holger 过滤函数的冗长度已经降低。 - srborlongan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接