Alıcıya yansıma yoluyla başvurmanın en iyi yolu


127

Belirli bir ek açıklamaya sahip bir alanın değerini almam gerekiyor, Yani yansıma ile bu Alan Nesnesini elde edebiliyorum. Sorun şu ki, bu alan her zaman özel olacak, ancak önceden bildiğim halde her zaman bir alıcı yöntemi olacak. Getter yöntemini çağırmayı tercih etsem de setAccesible (true) kullanıp değerini alabileceğimi (PermissionManager olmadığında) biliyorum.

Yöntemi "get + fieldName" i arayarak arayabileceğimi biliyorum (örneğin boole alanlarının bazen "is + fieldName" olarak adlandırıldığını biliyorum).

Bu alıcıyı çağırmanın daha iyi bir yolu olup olmadığını merak ediyorum (birçok çerçeve özniteliklere erişmek için alıcıları / ayarlayıcıları kullanır, bu yüzden belki başka bir şekilde yaparlar).

Teşekkürler

Yanıtlar:


242

Bunun sizi doğru yöne yönlendirmesi gerektiğini düşünüyorum:

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 veya PropertyDescriptor örneklerini kendiniz, yani Introspector kullanmadan oluşturabileceğinizi unutmayın. Bununla birlikte, Introspector, normalde iyi bir şey (tm) olan dahili olarak bir miktar önbellekleme yapar. Önbellek olmadan mutluysanız, gidebilirsiniz

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

Ancak, java.beans API'sini genişleten ve basitleştiren birçok kitaplık vardır. Commons BeanUtils iyi bilinen bir örnektir. Orada, basitçe yaparsınız:

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

BeanUtils başka kullanışlı şeylerle birlikte gelir. yani, kullanıcı girdisinden özelliklerin ayarlanmasını basitleştirmek için anında değer dönüşümü (nesneden dizgeye, dizgeden nesneye).


Çok teşekkür ederim! Bu beni dize manipülasyonlarından vb. Kurtardı!
guerda

1
Apache's BeanUtils için iyi çağrı. Özelliklerin alınmasını / ayarlanmasını kolaylaştırır ve tür dönüşümünü gerçekleştirir.
Peter Tseng

Yöntemleri, alanların Java dosyasında listelendiği sırada çağırmanın bir yolu var mı?
LifeAndHope

@Anand altında cevabım bak
Anand

Bayıldım! Muhteşem.
smilyface

20

Bunun için Yansımalar çerçevesini kullanabilirsiniz

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

Reflections'ın hala Java 9 ile uyumlu olmadığına dikkat edin . Daha iyi davranan ClassIndex (derleme zamanı) ve ClassGraph (çalıştırma zamanı) alternatifleri için bağlantılar vardır.
Vadzim

Bu çözüm ayrıca kabul edilen cevapta Bean Introspector'ın aksine * alıcıları da hesaba katmaz.
Vadzim


3

Yansımaları çağırabilir ve ayrıca ek açıklamalar aracılığıyla değerler için alıcı için sıra sırası ayarlayabilirsiniz.

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

Sıralandığında çıktı

getId Pos: 1 Value: 001
getName Pos: 2 Value: Anand
getGender Pos: 3 Value: Male
getGrade Pos: 4 Value: A
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.