Java Reflection: как я могу получить все методы getter classа java и вызывать их

Я пишу class java, который имеет много геттеров. Теперь я хочу получить все методы getter и вызывать их когда-нибудь. Я знаю, что существуют такие методы, как getMethods () или getMethod (имя строки, Class … parameterTypes), но i просто хочу получить геттер действительно …, используйте регулярное выражение? кто-нибудь может сказать мне? Спасибо!

Не используйте регулярное выражение, используйте 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, поэтому вы должны использовать метод с двумя параметрами:

 Introspector.getBeanInfo(yourClass, stopClass) // usually with Object.class as 2nd param // the first class is inclusive, the second exclusive 

Кстати: есть frameworks, которые делают это для вас и представляют вам представление высокого уровня. Например, commons / beanutils имеет метод

 Map properties = BeanUtils.describe(yourObject); 

( docs here ), который делает именно это: найти и выполнить все геттеры и сохранить результат на карте. К сожалению, BeanUtils.describe() преобразует все значения свойств в строки перед возвратом. WTF. Спасибо @danw


Обновить:

Вот метод Java 8, который возвращает Map основе свойств компонента объекта.

 public static Map 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(); } } 

Однако вы, вероятно, хотите сделать обработку ошибок более надежной. Извините за шаблон, проверенные исключения не позволяют нам полностью функционировать здесь.


Оказывается, что Collectors.toMap () ненавидит нулевые значения. Вот более настоятельная версия вышеуказанного кода:

 public static Map beanProperties(Object bean) { try { Map 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 :

 public static Map 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(); } } 

И вот версия Guava:

 public static Map 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::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); } } 

Вы можете использовать инфраструктуру Reflections для этого

 import org.reflections.ReflectionUtils.*; Set getters = ReflectionUtils.getAllMethods(someClass, ReflectionUtils.withModifier(Modifier.PUBLIC), ReflectionUtils.withPrefix("get")); 
  // 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()); } 

Spring предлагает простой метод BeanUtil для интроспекции Bean:

 PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(clazz, property); Method getter = pd.getReadMethod(); 

Этот код проверен ОК.

 private void callAllGetterMethodsInTestModel(TestModel testModelObject) { try { Class testModelClass = Class.forName("com.encoders.eva.testreflectionapi.TestModel"); Method[] methods = testModelClass.getDeclaredMethods(); ArrayList 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(); } } 

Вы должны поддерживать общий getter в каждом компоненте, чтобы вызвать getAttribute1 (), вы должны иметь возможность вызвать общий getter get («Attribute1»)

Этот общий геттер будет в свою очередь вызывать правильный приемник

 Object get(String attribute) { if("Attribute1".equals(attribute) { return getAttribute1(); } } 

Этот подход предполагает, что вы поддерживаете этот отдельный список в каждом компоненте, но таким образом избегаете отражения, которое имеет проблемы с производительностью, поэтому, если вы пишете производственный код, который должен иметь хорошую производительность, вы можете использовать приведенный выше шаблон для всех ваших компонентов.

Если это какой-то тестовый код или код утилиты, который не имеет высоких требований к производительности, вам лучше использовать другие подходы, поскольку этот подход подвержен ошибкам, если вы не можете написать какой-то счетчик времени компиляции, который гарантирует, что эта общая функция getter работает для всех атрибутов ,

  • Отражение Java: как получить значение поля от объекта, не зная его classа
  • Скопируйте все значения из полей одного classа в другой посредством отражения
  • Как получить строковое имя метода в java?
  • java: получить все имена переменных в classе
  • Вызов динамической функции Java
  • Отражение Java - влияние setAccessible (true)
  • Как использовать URLClassLoader для загрузки файла * .class?
  • Давайте будем гением компьютера.