Java 反射:如何获取 Java 类的所有 getter 方法并调用它们

新手上路,请多包涵

我写了一个有很多 getter 的 java 类。现在我想获取所有 getter 方法并在某个时候调用它们。我知道有诸如 getMethods() 或 getMethod(String name, Class… parameterTypes) 之类的方法,但是我确实只是想获得吸气剂…,使用正则表达式?谁能告诉我?谢谢!

原文由 user996505 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 851
2 个回答

不要使用正则表达式,使用 Introspector

 for(PropertyDescriptor propertyDescriptor :
    Introspector.getBeanInfo(yourClass).getPropertyDescriptors()){

    // propertyEditor.getReadMethod() exposes the getter
    // btw, this may be null if you have a write-only property
    System.out.println(propertyDescriptor.getReadMethod());
}

通常你不需要 Object.class 的属性,所以你会使用带有两个参数的方法:

 Introspector.getBeanInfo(yourClass, stopClass)
// usually with Object.class as 2nd param
// the first class is inclusive, the second exclusive

顺便说一句:有些框架可以为您做到这一点,并为您呈现一个高级视图。例如 commons/beanutils 有方法

Map<String, String> properties = BeanUtils.describe(yourObject);

这里的文档)就是这样做的:找到并执行所有的 getter 并将结果存储在地图中。不幸的是, BeanUtils.describe() 在返回之前将所有属性值转换为字符串。卧槽谢谢@danw


更新:

这是一个基于对象的 bean 属性返回 Map<String, Object> 的 Java 8 方法。

 public static Map<String, Object> beanProperties(Object bean) {
  try {
    return Arrays.asList(
         Introspector.getBeanInfo(bean.getClass(), Object.class)
                     .getPropertyDescriptors()
      )
      .stream()
      // filter out properties with setters only
      .filter(pd -> Objects.nonNull(pd.getReadMethod()))
      .collect(Collectors.toMap(
        // bean property name
        PropertyDescriptor::getName,
        pd -> { // invoke method to get value
            try {
                return pd.getReadMethod().invoke(bean);
            } catch (Exception e) {
                // replace this with better error handling
               return null;
            }
        }));
  } catch (IntrospectionException e) {
    // and this, too
    return Collections.emptyMap();
  }
}

不过,您可能希望使错误处理更加健壮。对样板感到抱歉,已检查的异常阻止我们在这里充分发挥作用。


原来 Collectors.toMap() 讨厌空值。下面是上述代码的命令式版本:

 public static Map<String, Object> beanProperties(Object bean) {
    try {
        Map<String, Object> map = new HashMap<>();
        Arrays.asList(Introspector.getBeanInfo(bean.getClass(), Object.class)
                                  .getPropertyDescriptors())
              .stream()
              // filter out properties with setters only
              .filter(pd -> Objects.nonNull(pd.getReadMethod()))
              .forEach(pd -> { // invoke method to get value
                  try {
                      Object value = pd.getReadMethod().invoke(bean);
                      if (value != null) {
                          map.put(pd.getName(), value);
                      }
                  } catch (Exception e) {
                      // add proper error handling here
                  }
              });
        return map;
    } catch (IntrospectionException e) {
        // and here, too
        return Collections.emptyMap();
    }
}

下面是使用 JavaSlang 以更简洁的方式实现的相同功能:

 public static Map<String, Object> javaSlangBeanProperties(Object bean) {
    try {
        return Stream.of(Introspector.getBeanInfo(bean.getClass(), Object.class)
                                     .getPropertyDescriptors())
                     .filter(pd -> pd.getReadMethod() != null)
                     .toJavaMap(pd -> {
                         try {
                             return new Tuple2<>(
                                     pd.getName(),
                                     pd.getReadMethod().invoke(bean));
                         } catch (Exception e) {
                             throw new IllegalStateException();
                         }
                     });
    } catch (IntrospectionException e) {
        throw new IllegalStateException();

    }
}

这是一个 Guava 版本:

 public static Map<String, Object> guavaBeanProperties(Object bean) {
    Object NULL = new Object();
    try {
        return Maps.transformValues(
                Arrays.stream(
                        Introspector.getBeanInfo(bean.getClass(), Object.class)
                                    .getPropertyDescriptors())
                      .filter(pd -> Objects.nonNull(pd.getReadMethod()))
                      .collect(ImmutableMap::<String, Object>builder,
                               (builder, pd) -> {
                                   try {
                                       Object result = pd.getReadMethod()
                                                         .invoke(bean);
                                       builder.put(pd.getName(),
                                                   firstNonNull(result, NULL));
                                   } catch (Exception e) {
                                       throw propagate(e);
                                   }
                               },
                               (left, right) -> left.putAll(right.build()))
                      .build(), v -> v == NULL ? null : v);
    } catch (IntrospectionException e) {
        throw propagate(e);
    }
}

原文由 Sean Patrick Floyd 发布,翻译遵循 CC BY-SA 3.0 许可协议

您可以为此使用 反射 框架

import org.reflections.ReflectionUtils.*;
Set<Method> getters = ReflectionUtils.getAllMethods(someClass,
      ReflectionUtils.withModifier(Modifier.PUBLIC), ReflectionUtils.withPrefix("get"));

原文由 Naveedur Rahman 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题