我有一个类Foo,它是Bar。
类型的属性public class Foo {
public Bar getBar() {
}
}
public class Bar {
public String getName();
}
是否有帮助程序类或方法使用java.lang.reflect.Method
和“bar.name”来获取Bar
名称属性的Foo.class
对象?
Commons BeanUtils中有一个名为PropertyUtils
的类,但其getPropertyDescriptor()
仅适用于Object
个实例,而不适用于Class
个实例。
我意识到实施一个并不难,但我想利用现有的功能。
另外,我需要一个Method对象的事实不是糟糕设计的结果(希望不是)。我正在研究的几乎是JavaBeans编辑器。
谢谢!
答案 0 :(得分:2)
在这里你可以寻找嵌套支持: 根据用例,可以缓存检索到的类。例如,在使用重过滤的数据表crud应用程序中。
/**
* Retrieves the type of the property with the given name of the given
* Class.<br>
* Supports nested properties following bean naming convention.
*
* "foo.bar.name"
*
* @see PropertyUtils#getPropertyDescriptors(Class)
*
* @param clazz
* @param propertyName
*
* @return Null if no property exists.
*/
public static Class<?> getPropertyType(Class<?> clazz, String propertyName)
{
if (clazz == null)
throw new IllegalArgumentException("Clazz must not be null.");
if (propertyName == null)
throw new IllegalArgumentException("PropertyName must not be null.");
final String[] path = propertyName.split("\\.");
for (int i = 0; i < path.length; i++)
{
propertyName = path[i];
final PropertyDescriptor[] propDescs = PropertyUtils.getPropertyDescriptors(clazz);
for (final PropertyDescriptor propDesc : propDescs)
if (propDesc.getName().equals(propertyName))
{
clazz = propDesc.getPropertyType();
if (i == path.length - 1)
return clazz;
}
}
return null;
}
答案 1 :(得分:1)
在Commons BeanUtils中,PropertyUtils.getPropertyDescriptors()
将Class
作为输入并返回PropertyDescriptor
数组。
我不知道它是否会返回“嵌套”名称,例如bar.name
,但如果没有,则不应该太难以对结果进行递归并构建自己的嵌套名称列表。
只是快速进行健全检查......世界真的需要另一个JavaBeans编辑器吗?
答案 2 :(得分:1)
我会使用MVEL或OGNL并跳过“我需要方法对象”的要求。
答案 3 :(得分:0)
这是djmj answer的一个版本,如果有人感兴趣,Java 8流将返回Optional。
/**
* Retrieves the type of the property with the given name of the given Class.
*
* Supports nested properties following bean naming convention "foo.bar.name"
*
* @return Optional.empty if no property exists.
* @see PropertyUtils#getPropertyDescriptors(Class)
*/
public static Optional<Class<?>> findPropertyType(@NotNull Class<?> clazz, @NotBlank String propertyName) {
return Arrays.stream(propertyName.split("\\.")).reduce(
Optional.ofNullable(clazz), // identity -> initial value of the accumulator
(Optional<Class<?>> accOptClazz, String nextPropertyName) -> // accumulator with current value and next value from string
stream(accOptClazz)
.map((Class<?> accClazz) -> Arrays.stream(PropertyUtils.getPropertyDescriptors(accClazz)))
.flatMap(Function.identity())
.filter(propDesc -> propDesc.getName().equals(nextPropertyName))
.findFirst().map(PropertyDescriptor::getPropertyType),
(clazzA, clazzB) -> null // needed but useless combiner (only for parallel reduce)
);
}
/**
* Turns an Optional<T> into a Stream<T> of length zero or one depending upon whether a value is present.
*/
public static <T> Stream<T> stream(Optional<T> opt) {
return opt.isPresent() ? Stream.of(opt.get()) : Stream.empty();
}
答案 4 :(得分:0)
通过尝试将 Spring Data Sort 转换为 Comparator 到这里。
public class ComparatorUtils {
public static <T> Comparator<T> fromSort(Sort sort, Class<T> type) {
final Iterator<Sort.Order> orderIterator = sort.iterator();
final Sort.Order order = orderIterator.next();
Comparator<T> comparator = fromSortOrder(order, type);
while (orderIterator.hasNext()) {
comparator = comparator.thenComparing(fromSortOrder(orderIterator.next(), type));
}
return comparator;
}
private static <T> Comparator<T> fromSortOrder(Sort.Order order, Class<T> type) {
final List<Method> accessMethods = new ArrayList<>();
Class<?> currentClass = type;
for (String property : order.getProperty().split("\\.")) {
Method m = Objects.requireNonNull(BeanUtils.getPropertyDescriptor(currentClass, property)).getReadMethod();
accessMethods.add(m);
currentClass = m.getReturnType();
}
Comparator<T> comparator = Comparator.comparing((T entity) -> {
try {
Object result = entity;
for (Method method : accessMethods) {
result = method.invoke(result);
}
return (Comparable) result;
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}, Comparator.nullsLast(Comparator.naturalOrder()));
if (order.isDescending())
return comparator.reversed();
return comparator;
}
}