วิธีที่ดีที่สุดในการเรียกร้องความสนใจโดยการไตร่ตรอง


127

ฉันต้องการรับค่าของฟิลด์ที่มีคำอธิบายประกอบเฉพาะดังนั้นด้วยการสะท้อนฉันจึงได้รับ Field Object นี้ ปัญหาคือฟิลด์นี้จะเป็นแบบส่วนตัวเสมอแม้ว่าฉันจะรู้ล่วงหน้าว่ามันจะมีวิธี getter เสมอ ฉันรู้ว่าฉันสามารถใช้ setAccesible (true) และรับค่าของมันได้ (เมื่อไม่มี PermissionManager) แม้ว่าฉันจะชอบเรียกใช้เมธอด getter ก็ตาม

ฉันรู้ว่าฉันสามารถค้นหาเมธอดได้โดยค้นหา "get + fieldName" (แม้ว่าฉันจะรู้ว่าบางครั้งฟิลด์บูลีนจะถูกตั้งชื่อเป็น "is + fieldName")

ฉันสงสัยว่ามีวิธีที่ดีกว่าในการเรียกใช้ getter นี้หรือไม่ (เฟรมเวิร์กจำนวนมากใช้ getters / setters เพื่อเข้าถึงแอตทริบิวต์ดังนั้นอาจใช้วิธีอื่น)

ขอบคุณ

คำตอบ:


242

ฉันคิดว่าสิ่งนี้ควรชี้ให้คุณไปสู่ทิศทางที่ถูกต้อง:

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 มาพร้อมกับของใช้อื่น ๆ เช่นการแปลงค่าแบบทันที (object to string, string to object) เพื่อลดความซับซ้อนของคุณสมบัติการตั้งค่าจากอินพุตของผู้ใช้


ขอบคุณมาก! สิ่งนี้ช่วยฉันจากการปรับแต่งสตริง ฯลฯ !
guerda

1
ขอให้ดีกับ BeanUtils ของ Apache ทำให้การรับ / การตั้งค่าคุณสมบัติง่ายขึ้นและจัดการการแปลงประเภท
Peter Tseng

มีวิธีเรียกใช้เมธอดตามลำดับฟิลด์ที่แสดงรายการในไฟล์ Java หรือไม่
LifeAndHope

ดูคำตอบของฉันด้านล่าง @Anand
Anand

รักมัน ! น่ากลัว
smilyface

20

คุณสามารถใช้กรอบการสะท้อนสำหรับสิ่งนี้

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

ระวังว่า Reflections ยังไม่สามารถทำงานร่วมกับ Java 9ได้ มีลิงก์สำหรับการทำงานที่ดีขึ้นClassIndex (เวลาคอมไพล์) และทางเลือกClassGraph (เวลาทำงาน) จาก threre
Vadzim

โซลูชันนี้ยังไม่ได้คำนึงถึงคือ * getters ต่างจาก bean Introspector ในคำตอบที่ยอมรับ
Vadzim


3

คุณสามารถเรียกใช้การสะท้อนและกำหนดลำดับของลำดับสำหรับ 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.