Java 反射:如何获取 Java 类的所有 getter 方法并调用它们 [英] Java Reflection: How can I get the all getter methods of a java class and invoke them
问题描述
我写了一个有很多 getter 的 java 类..现在我想获取所有的 getter 方法并在某个时候调用它们..我知道有 getMethods() 或 getMethod(String name, Class... parameterTypes) 等方法,但我只是想得到真正的吸气剂......,使用正则表达式?谁能告诉我?谢谢!
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!
推荐答案
不要使用正则表达式,使用 Introspector
:
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());
}
通常你不想要 Object.class 的属性,所以你会使用带有两个参数的方法:
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
顺便说一句:有些框架可以为您做到这一点并为您提供高级视图.例如.commons/beanutils 有方法
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) 就是这样做的:查找并执行所有 getter 并将结果存储在地图中.不幸的是,BeanUtils.describe()
在返回之前将所有属性值转换为字符串.跆拳道.谢谢@danw
(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
更新:
这是一个 Java 8 方法,它根据对象的 bean 属性返回一个 Map
.
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.
事实证明 Collectors.toMap() 讨厌空值.下面是上述代码的一个更命令的版本:
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();
}
}
以下是使用 JavaSlang 以更简洁的方式实现的相同功能:
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();
}
}
这是番石榴版本:
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);
}
}
这篇关于Java 反射:如何获取 Java 类的所有 getter 方法并调用它们的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!