Java Reflection: How to Get the All Getter Methods of a Java Class and Invoke Them

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

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

How to call all getter methods of a class in a loop?

You could access declared methods of a class that way:

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Other {

public static void main(String [] args) {

Person p = new Person("Max", 12);
Class<?> c = p.getClass();
Method[] allMethods = c.getDeclaredMethods();

System.out.print( "Person's attributes: ");
for (Method m : allMethods) {
m.setAccessible(true);
String result;
try {
result = m.invoke(p).toString();
System.out.print(result + " ");
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}

}
}
}

class Person {
String name;
int age;

public Person(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public int getAge() {
return age;
}

}```

Reflector: How to list getters of a class and invoke them in Java?

PropertyDescriptor.getReadMethod() returns a Method object.

Simply use Method.invoke(Object instance, Object... args).

Something in the lines of...

for(PropertyDescriptor propertyDescriptor : 
Introspector.getBeanInfo(User.class,Object.class).getPropertyDescriptors()){
try {
Object value = propertyDescriptor
.getReadMethod()

.invoke(myUserInstance, (Object[])null);
}
catch (IllegalAccessException iae) {
// TODO
}
catch (IllegalArgumentException iaee) {
// TODO
}
catch (InvocationTargetException ite) {
// TODO
}
}

Java Reflection : Accessing getter method

DEfine the class, then in the instance get all the methods then use a stream to filter the getters only

public class Pint {

private int x;
private int y;
private int z;

public int getX() {
return x;
}

public int getY() {
return y;
}

public int getZ() {
return z;
}

and then

 Arrays.stream(p.getClass().getDeclaredMethods()).filter(x -> x.getName().contains("get")).forEach(System.out::println);

Best way of invoking getter by reflection

I think this should point you towards the right direction:

import java.beans.*

for (PropertyDescriptor pd : Introspector.getBeanInfo(Foo.class).getPropertyDescriptors()) {
if (pd.getReadMethod() != null && !"class".equals(pd.getName()))
System.out.println(pd.getReadMethod().invoke(foo));
}

Note that you could create BeanInfo or PropertyDescriptor instances yourself, i.e. without using Introspector. However, Introspector does some caching internally which is normally a Good Thing (tm). If you're happy without a cache, you can even go for

// TODO check for non-existing readMethod
Object value = new PropertyDescriptor("name", Person.class).getReadMethod().invoke(person);

However, there are a lot of libraries that extend and simplify the java.beans API. Commons BeanUtils is a well known example. There, you'd simply do:

Object value = PropertyUtils.getProperty(person, "name");

BeanUtils comes with other handy stuff. i.e. on-the-fly value conversion (object to string, string to object) to simplify setting properties from user input.

Java reflection - how to call getter/setter method?

currentObject.getClass().getMethod(methodName);

Since methods can be overloaded, just the name of the method is not enough to look up the method. You need to provide the types of the arguments as well (and a setter is typically not a no-arg method).

Try something like

currentObject.getClass().getMethod(methodName, objectInputArr[i].getClass());
^^^^^^^^^^^^^^^^^^^^^^^^^^^^


Related Topics



Leave a reply



Submit