I write a java class which has many getters..now I want to get all getter methods and invoke them sometime..I know there are methods such as getMethods() or getMethod(String name, Class... parameterTypes) ,but i just want to get the getter indeed..., use regex? anyone can tell me ?Thanks!
Don't use regex, use the 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()); }
Usually you don't want properties from Object.class, so you'd use the method with two parameters:
Introspector.getBeanInfo(yourClass, stopClass) // usually with Object.class as 2nd param // the first class is inclusive, the second exclusive
BTW: there are frameworks that do that for you and present you a high-level view. E.g. commons/beanutils has the method
Map<String, String> properties = BeanUtils.describe(yourObject);
(docs here) which does just that: find and execute all the getters and store the result in a map. Unfortunately, BeanUtils.describe()
converts all the property values to Strings before returning. WTF. Thanks @danw
Update:
Here's a Java 8 method that returns a Map<String, Object>
based on an object's bean properties.
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(); } }
You probably want to make error handling more robust, though. Sorry for the boilerplate, checked exceptions prevent us from going fully functional here.
Turns out that Collectors.toMap() hates null values. Here's a more imperative version of the above code:
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(); } }
Here's the same functionality in a more concise way, using 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(); } }
And here's a Guava version:
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); } }
You can use Reflections framework for this
import org.reflections.ReflectionUtils.*; Set<Method> getters = ReflectionUtils.getAllMethods(someClass, ReflectionUtils.withModifier(Modifier.PUBLIC), ReflectionUtils.withPrefix("get"));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With