代码之家  ›  专栏  ›  技术社区  ›  Javi

通过反射调用getter的最佳方法

  •  111
  • Javi  · 技术社区  · 15 年前

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

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

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

    谢谢

    4 回复  |  直到 8 年前
        1
  •  213
  •   Johnny Bones    10 年前

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

    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实例,也就是说,不需要使用内省器。然而,内省器在内部执行一些缓存,这通常是一件好事(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还有其他方便的东西。即动态值转换(对象到字符串、字符串到对象),以简化用户输入的设置属性。

        2
  •  17
  •   Dimitri    8 年前

    你可以用 Reflections 此框架

    import static org.reflections.ReflectionUtils.*;
    Set<Method> getters = ReflectionUtils.getAllMethods(someClass,
          withModifier(Modifier.PUBLIC), withPrefix("get"), withAnnotation(annotation));
    
        3
  •  4
  •   Michael Borgwardt    15 年前

    命名约定是已建立的 JavaBeans 规范,并由中的类支持 java.beans 包裹。

        4
  •  2
  •   Anand    10 年前

    您可以调用反射,也可以通过注释为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