Javareflection:我怎样才能得到一个Java类的所有getter方法,并调用它们

我写了一个有很多getter的java类。现在我想要获取所有的getter方法,并在某个时候调用它们。我知道有方法,如getMethods()或getMethod(String name,Class … parameterTypes),但我只是想得到getter的确,…使用正则expression式? 任何人都可以告诉我?谢谢!

不要使用正则expression式,使用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); 

( docs here )就是这样做的:find并执行所有的getter并将结果存储在地图中。 不幸的是, BeanUtils.describe()在返回之前将所有的属性值转换为string。 WTF。 谢谢@danw


更新:

这是一个Java 8方法,它根据对象的bean属性返回一个Map<String, Object>

 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(); } } 

虽然你可能想要使error handling更健壮。 对不起,对于样板,检查exception阻止我们在这里function齐全。


原来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 ,以更简洁的方式显示相同的function:

 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(); } } 

这是一个番石榴版本:

 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); } } 

你可以使用这个reflection框架

 import org.reflections.ReflectionUtils.*; Set<Method> getters = ReflectionUtils.getAllMethods(someClass, ReflectionUtils.withModifier(Modifier.PUBLIC), ReflectionUtils.withPrefix("get")); 
  // Get the Class object associated with this class. MyClass myClass= new MyClass (); Class objClass= myClass.getClass(); // Get the public methods associated with this class. Method[] methods = objClass.getMethods(); for (Method method:methods) { System.out.println("Public method found: " + method.toString()); } 

Spring为Bean内省提供了一个简单的BeanUtil方法 :

 PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(clazz, property); Method getter = pd.getReadMethod(); 

你应该在每个bean中维护一个通用的getter,以便调用getAttribute1(),你应该能够调用一个通用的getter get(“Attribute1”)

这个通用的getter将会依次调用正确的getter

 Object get(String attribute) { if("Attribute1".equals(attribute) { return getAttribute1(); } } 

这种方法涉及到在每个bean中维护这个单独的列表,但是这样可以避免出现性能问题的reflection,因此如果您要编写需要具有良好性能的生产代码,则可以对上述所有bean使用上述模式。

如果它是一些testing代码或者没有高性能要求的工具代码,那么你最好采取其他方法,因为这种方法很容易出错,除非你可以编写一些编译时检查器来确保这个通用的getter函数适用于所有的属性。