Java Reflection:如何获取java类的所有getter方法并调用它们

发布于 2024-12-21 05:16:15 字数 168 浏览 2 评论 0原文

我编写了一个有很多 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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

女皇必胜 2024-12-28 05:16:15

不要使用正则表达式,使用 Introspector< /code>

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

顺便说一句:有些框架可以为您执行此操作并为您提供高级视图。例如
commons/beanutils 有方法

Map<String, String> properties = BeanUtils.describe(yourObject);

(docs here) 的作用就是:查找并执行所有 getter 并将结果存储在映射中。不幸的是,BeanUtils.describe() 在返回之前将所有属性值转换为字符串。 WTF。谢谢@danw


更新:

这是一个 Java 8 方法,它根据对象的 bean 属性返回 Map

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

不过,您可能希望使错误处理更加健壮。对样板文件感到抱歉,检查的异常阻止我们在这里充分发挥作用。


事实证明 Collectors.toMap() 讨厌空值。这是上述代码的更命令式版本:

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 以更简洁的方式实现相同功能的方式:

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);
    }
}

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);
    }
}
你又不是我 2024-12-28 05:16:15

您可以使用 Reflections 框架来实现此目的

import org.reflections.ReflectionUtils.*;
Set<Method> getters = ReflectionUtils.getAllMethods(someClass,
      ReflectionUtils.withModifier(Modifier.PUBLIC), ReflectionUtils.withPrefix("get"));

You can use Reflections framework for this

import org.reflections.ReflectionUtils.*;
Set<Method> getters = ReflectionUtils.getAllMethods(someClass,
      ReflectionUtils.withModifier(Modifier.PUBLIC), ReflectionUtils.withPrefix("get"));
婴鹅 2024-12-28 05:16:15

Spring 提供了一个简单的 BeanUtil 方法 用于 Bean 自省:

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

Spring offers an easy BeanUtil method for Bean introspection:

PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(clazz, property);
Method getter = pd.getReadMethod();
沦落红尘 2024-12-28 05:16:15
 // 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());
    }
 // 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());
    }
沫离伤花 2024-12-28 05:16:15

为什么不使用简单的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;
}

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;
}

...

一场春暖 2024-12-28 05:16:15

这段代码经测试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();
        }
    }

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();
        }
    }
小…楫夜泊 2024-12-28 05:16:15
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;
                        }
                    }));
}
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;
                        }
                    }));
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文