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

JavaReflection

Java Problem Overview


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!

Java Solutions


Solution 1 - Java

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

Solution 2 - Java

You can use Reflections framework for this

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

Solution 3 - Java

Spring offers an easy BeanUtil method for Bean introspection:

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

Solution 4 - Java

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

Solution 5 - Java

Why not use simple Java? ...

public static Map<String, Object> beanProperties(final Object bean) {
	final Map<String, Object> result = new HashMap<String, Object>();

	try {
		final PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(bean.getClass(), Object.class).getPropertyDescriptors();
		for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
			final Method readMethod = propertyDescriptor.getReadMethod();
			if (readMethod != null) {
				result.put(propertyDescriptor.getName(), readMethod.invoke(bean, (Object[]) null));
			}
		}
	} catch (Exception ex) {
		// ignore
	}

	return result;
}

...

Solution 6 - Java

This code is tested OK.

private void callAllGetterMethodsInTestModel(TestModel testModelObject) {
        try {
            Class testModelClass = Class.forName("com.example.testreflectionapi.TestModel");
            Method[] methods = testModelClass.getDeclaredMethods();
            ArrayList<String> getterResults = new ArrayList<>();
            for (Method method :
                    methods) {
                if (method.getName().startsWith("get")){
                    getterResults.add((String) method.invoke(testModelObject));
                }
            }
            Log.d("sayanReflextion", "==>: "+getterResults.toString());
        } catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }

Solution 7 - Java

public static void retrieveAndExecuteBeanGetterMethods(Object bean) throws IntrospectionException {
    List<PropertyDescriptor> beanGettersList = Arrays.asList(
            Introspector.getBeanInfo(bean.getClass(), Object.class)
                    .getPropertyDescriptors());

    beanGettersList.stream()
            .filter(pd -> Objects.nonNull(pd.getReadMethod()))
            .collect(Collectors.toMap(PropertyDescriptor::getName,
                    pd -> {
                        try {
                            return pd.getReadMethod().invoke(bean);
                        } catch (Exception e) {
                            return null;
                        }
                    }));
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser996505View Question on Stackoverflow
Solution 1 - JavaSean Patrick FloydView Answer on Stackoverflow
Solution 2 - JavaNaveedur RahmanView Answer on Stackoverflow
Solution 3 - JavaStefan HaberlView Answer on Stackoverflow
Solution 4 - Javadku.rajkumarView Answer on Stackoverflow
Solution 5 - JavaAntoniusView Answer on Stackoverflow
Solution 6 - JavaSayan MukherjeeView Answer on Stackoverflow
Solution 7 - JavaIng. VikView Answer on Stackoverflow