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);
}
}
BeanUtils.describe(yourObject);
returns Map<String, String>
not Map<String, Object>`. –
Macy propertyDescriptor.getName()
is defined. Of course that doesn't verify that the getter actually reads this field, but it's a start. –
Hafnium You can use Reflections framework for this
import org.reflections.ReflectionUtils.*;
Set<Method> getters = ReflectionUtils.getAllMethods(someClass,
ReflectionUtils.withModifier(Modifier.PUBLIC), ReflectionUtils.withPrefix("get"));
Spring offers an easy BeanUtil method for Bean introspection:
PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(clazz, property);
Method getter = pd.getReadMethod();
BeanUtils.getPropertyDescriptors(clazz)
to get all properties. –
Canikin // 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());
}
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;
}
...
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();
}
}
get
does not mean it's a getter. –
Ultraviolet if (name.startsWith(GET_PREFIX))
docjar.com/html/api/java/beans/Introspector.java.html#511 –
Jetblack 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;
}
}));
}
© 2022 - 2024 — McMap. All rights reserved.