Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Reflection: How can I get the all getter methods of a java class and invoke them

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!

like image 519
user996505 Avatar asked Dec 15 '11 17:12

user996505


2 Answers

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);     } } 
like image 77
Sean Patrick Floyd Avatar answered Sep 18 '22 18:09

Sean Patrick Floyd


You can use Reflections framework for this

import org.reflections.ReflectionUtils.*; Set<Method> getters = ReflectionUtils.getAllMethods(someClass,       ReflectionUtils.withModifier(Modifier.PUBLIC), ReflectionUtils.withPrefix("get")); 
like image 44
Naveedur Rahman Avatar answered Sep 20 '22 18:09

Naveedur Rahman