【问题标题】:Best way of invoking getter by reflection通过反射调用getter的最佳方式
【发布时间】:2010-04-14 15:14:54
【问题描述】:

我需要获取具有特定注释的字段的值,因此通过反射我能够获取此字段对象。问题是这个字段总是私有的,尽管我事先知道它总是有一个 getter 方法。我知道我可以使用 setAccesible(true) 并获取它的值(当没有 PermissionManager 时),但我更喜欢调用它的 getter 方法。

我知道我可以通过查找“get+fieldName”来查找方法(尽管我知道例如布尔字段有时被命名为“is+fieldName”)。

我想知道是否有更好的方法来调用这个 getter(许多框架使用 getter/setter 来访问属性,所以也许他们以另一种方式来做)。

谢谢

【问题讨论】:

    标签: java reflection getter


    【解决方案1】:

    我认为这应该为您指明正确的方向:

    import java.beans.*
    
    for (PropertyDescriptor pd : Introspector.getBeanInfo(Foo.class).getPropertyDescriptors()) {
      if (pd.getReadMethod() != null && !"class".equals(pd.getName()))
        System.out.println(pd.getReadMethod().invoke(foo));
    }
    

    请注意,您可以自己创建 BeanInfo 或 PropertyDescriptor 实例,即不使用 Introspector。但是,Introspector 会在内部进行一些缓存,这通常是一件好事 (tm)。如果您对没有缓存感到满意,您甚至可以选择

    // TODO check for non-existing readMethod
    Object value = new PropertyDescriptor("name", Person.class).getReadMethod().invoke(person);
    

    但是,有很多库可以扩展和简化 java.beans API。 Commons BeanUtils 是一个众所周知的例子。在那里,您只需这样做:

    Object value = PropertyUtils.getProperty(person, "name");
    

    BeanUtils 附带了其他方便的东西。即即时值转换(对象到字符串,字符串到对象)以简化用户输入的设置属性。

    【讨论】:

    • 非常感谢!这使我免于字符串操作等!
    • 对 Apache 的 BeanUtils 的好评。使获取/设置属性更容易,并处理类型转换。
    • 有没有办法按照字段在Java文件中列出的顺序调用方法?
    • 看我下面@Anand的回答
    • 喜欢它!太棒了。
    【解决方案2】:

    您可以为此使用Reflections 框架

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

    【讨论】:

    • 请注意,Reflections 仍然是 not compatible with Java 9。有更好的行为链接ClassIndex(编译时)和ClassGraph(运行时)来自threre的替代方案。
    • 这个解决方案也没有考虑到 is* getters 不像 bean Introspector 在接受的答案中。
    【解决方案3】:

    命名约定是完善的JavaBeans 规范的一部分,并受到java.beans 包中的类的支持。

    【讨论】:

      【解决方案4】:

      您可以调用反射,也可以通过注解设置 getter 的序列顺序

      public class Student {
      
          private String grade;
      
          private String name;
      
          private String id;
      
          private String gender;
      
          private Method[] methods;
      
          @Retention(RetentionPolicy.RUNTIME)
          public @interface Order {
              int value();
          }
      
          /**
           * Sort methods as per Order Annotations
           * 
           * @return
           */
          private void sortMethods() {
      
              methods = Student.class.getMethods();
      
              Arrays.sort(methods, new Comparator<Method>() {
                  public int compare(Method o1, Method o2) {
                      Order or1 = o1.getAnnotation(Order.class);
                      Order or2 = o2.getAnnotation(Order.class);
                      if (or1 != null && or2 != null) {
                          return or1.value() - or2.value();
                      }
                      else if (or1 != null && or2 == null) {
                          return -1;
                      }
                      else if (or1 == null && or2 != null) {
                          return 1;
                      }
                      return o1.getName().compareTo(o2.getName());
                  }
              });
          }
      
          /**
           * Read Elements
           * 
           * @return
           */
          public void readElements() {
              int pos = 0;
              /**
               * Sort Methods
               */
              if (methods == null) {
                  sortMethods();
              }
              for (Method method : methods) {
                  String name = method.getName();
                  if (name.startsWith("get") && !name.equalsIgnoreCase("getClass")) {
                      pos++;
                      String value = "";
                      try {
                          value = (String) method.invoke(this);
                      }
                      catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                          e.printStackTrace();
                      }
                      System.out.println(name + " Pos: " + pos + " Value: " + value);
                  }
              }
          }
      
          // /////////////////////// Getter and Setter Methods
      
          /**
           * @param grade
           * @param name
           * @param id
           * @param gender
           */
          public Student(String grade, String name, String id, String gender) {
              super();
              this.grade = grade;
              this.name = name;
              this.id = id;
              this.gender = gender;
          }
      
          /**
           * @return the grade
           */
          @Order(value = 4)
          public String getGrade() {
              return grade;
          }
      
          /**
           * @param grade the grade to set
           */
          public void setGrade(String grade) {
              this.grade = grade;
          }
      
          /**
           * @return the name
           */
          @Order(value = 2)
          public String getName() {
              return name;
          }
      
          /**
           * @param name the name to set
           */
          public void setName(String name) {
              this.name = name;
          }
      
          /**
           * @return the id
           */
          @Order(value = 1)
          public String getId() {
              return id;
          }
      
          /**
           * @param id the id to set
           */
          public void setId(String id) {
              this.id = id;
          }
      
          /**
           * @return the gender
           */
          @Order(value = 3)
          public String getGender() {
              return gender;
          }
      
          /**
           * @param gender the gender to set
           */
          public void setGender(String gender) {
              this.gender = gender;
          }
      
          /**
           * Main
           * 
           * @param args
           * @throws IOException
           * @throws SQLException
           * @throws InvocationTargetException
           * @throws IllegalArgumentException
           * @throws IllegalAccessException
           */
          public static void main(String args[]) throws IOException, SQLException, IllegalAccessException,
                  IllegalArgumentException, InvocationTargetException {
              Student student = new Student("A", "Anand", "001", "Male");
              student.readElements();
          }
        }
      

      排序后的输出

      getId Pos: 1 Value: 001
      getName Pos: 2 Value: Anand
      getGender Pos: 3 Value: Male
      getGrade Pos: 4 Value: A
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多