Cách tốt nhất để gọi getter bằng phản xạ


127

Tôi cần nhận được giá trị của một trường với một chú thích cụ thể, vì vậy với sự phản chiếu tôi có thể có được Đối tượng trường này. Vấn đề là lĩnh vực này sẽ luôn riêng tư mặc dù tôi biết trước nó sẽ luôn có một phương thức getter. Tôi biết rằng tôi có thể sử dụng setAccesible (true) và nhận giá trị của nó (khi không có PermissionManager), mặc dù tôi thích gọi phương thức getter của nó.

Tôi biết rằng tôi có thể tìm kiếm phương thức bằng cách tìm kiếm "get + fieldName" (mặc dù tôi biết ví dụ cho các trường boolean đôi khi được đặt tên là "is + fieldName").

Tôi tự hỏi liệu có cách nào tốt hơn để gọi getter này không (nhiều khung sử dụng getters / setters để truy cập các thuộc tính để có thể chúng làm theo cách khác).

Cảm ơn

Câu trả lời:


240

Tôi nghĩ rằng điều này sẽ chỉ cho bạn đi đúng hướng:

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

Lưu ý rằng bạn có thể tự tạo các phiên bản BeanInfo hoặc PropertyDescriptor mà không cần sử dụng Introspector. Tuy nhiên, Introspector thực hiện một số bộ nhớ đệm bên trong thường là một điều tốt (tm). Nếu bạn hài lòng mà không có bộ đệm, bạn thậm chí có thể đi

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

Tuy nhiên, có rất nhiều thư viện mở rộng và đơn giản hóa API java.beans. Commons BeanUtils là một ví dụ nổi tiếng. Ở đó, bạn chỉ cần làm:

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

BeanUtils đi kèm với những thứ tiện dụng khác. tức là chuyển đổi giá trị nhanh chóng (đối tượng thành chuỗi, chuỗi thành đối tượng) để đơn giản hóa các thuộc tính cài đặt từ đầu vào của người dùng.


Cảm ơn rât nhiều! Điều này tránh cho tôi khỏi các thao tác chuỗi vv!
guerda

1
Cuộc gọi tốt trên BeanUtils của Apache. Làm cho việc nhận / thiết lập các thuộc tính dễ dàng hơn và xử lý chuyển đổi loại.
Peter Tseng

Có cách nào để gọi các phương thức theo thứ tự các trường được liệt kê trong tệp Java không?
LifeAnd thịnh

Hãy xem câu trả lời của tôi dưới đây @Anand
Anand

Đã yêu nó ! Tuyệt vời.
smilyface

20

Bạn có thể sử dụng khung Reflection cho việc này

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

Coi chừng rằng Reflection vẫn không tương thích với Java 9 . Có các liên kết để thay thế tốt hơn các chỉ số Class Index (thời gian biên dịch) và ClassGraph (thời gian chạy) từ threre.
Vadzim

Giải pháp này cũng không được tính đến là * getters không giống như Bean Introspector trong câu trả lời được chấp nhận.
Vadzim


3

Bạn có thể gọi các phản xạ và cũng có thể, đặt thứ tự chuỗi cho getter cho các giá trị thông qua các chú thích

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

Đầu ra khi được sắp xếp

getId Pos: 1 Value: 001
getName Pos: 2 Value: Anand
getGender Pos: 3 Value: Male
getGrade Pos: 4 Value: A
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.