Как получить метод вложенного свойства? - PullRequest
2 голосов
/ 28 декабря 2010

У меня есть класс Foo, который является свойством типа Bar.

public class Foo {
    public Bar getBar() {

    }
}

public class Bar {
    public String getName();
}

Есть ли вспомогательный класс или метод, который возвращает вам java.lang.reflect.Method объект со свойством name Bar, используяFoo.class и "bar.name"?

В Commons BeanUtils есть класс PropertyUtils, но его getPropertyDescriptor() работает только для Object экземпляров, но не Class.

Я понимаю, что реализовать совсем не сложно, но я бы хотел использовать то, что уже доступно.

Кроме того, тот факт, что мне нужен объект Method, не является результатом плохого дизайна (надеюсь,не).Я работаю над редактором JavaBeans.

Спасибо!

Ответы [ 4 ]

2 голосов
/ 30 мая 2013

Здесь вы найдете вложенную поддержку: в зависимости от варианта использования извлеченные классы могут быть кэшированы.Например, в приложении Datatable 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 голос
/ 28 декабря 2010

Я бы пошел с MVEL или OGNL и пропустил требование "Мне нужен объект метода".

1 голос
/ 28 декабря 2010

В Commons BeanUtils PropertyUtils.getPropertyDescriptors() принимает Class в качестве входных данных и возвращает массив PropertyDescriptor.

Я не знаю, будет ли он возвращать "вложенные" имена, такие как bar.nameно если нет, то не должно быть слишком сложно оценить результат и составить собственный список вложенных имен.

Хотя бы просто быстрая проверка работоспособности ... действительно ли миру нужен еще один редактор JavaBeans?

0 голосов
/ 16 мая 2019

Вот версия из djmj answer с возвращением потоков Java 8 Необязательно, если кому-то интересно

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