2010-04-14 16 views
99

Potrzebuję uzyskać wartość pola z określoną adnotacją, Więc z odbiciem jestem w stanie uzyskać ten obiekt pola. Problem polega na tym, że to pole będzie zawsze prywatne, choć wiem z góry, że zawsze będzie miało metodę gettera. Wiem, że mogę użyć setAccesible (true) i uzyskać jego wartość (gdy nie ma PermissionManager), chociaż wolę wywołać jego metodę getter.Najlepszy sposób wywoływania gettera przez odbicie

Wiem, że mogłem poszukać metody, szukając "get + fieldName" (chociaż wiem na przykład, że pola boolowskie są czasami nazywane "is + fieldName").

Zastanawiam się, czy istnieje lepszy sposób na wywołanie tego gettera (wiele frameworków używa getter/setters, aby uzyskać dostęp do atrybutów, więc może robią to w inny sposób).

Dzięki

Odpowiedz

195

myślę, że to powinno wskazać w kierunku właściwym kierunku:

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

Należy pamiętać, że można tworzyć BeanInfo lub PropertyDescriptor instancji samodzielnie, to znaczy bez użycia Introspector. Jednak introspektor dokonuje wewnętrznego buforowania, co zwykle jest Dobrą Rzeczą (tm). Jeśli jesteś szczęśliwy bez pamięci podręcznej, można nawet iść do

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

Jednakże, istnieje wiele bibliotek, które rozciągają się i uproszczenia java.beans API. Commons BeanUtils jest dobrze znanym przykładem. W takim przypadku wystarczy:

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

BeanUtils zawiera inne przydatne rzeczy. tj. konwersja wartości w locie (obiekt do napisu, ciąg do obiektu), aby uprościć ustawianie właściwości na podstawie danych wprowadzanych przez użytkownika.

+2

+1 po prostu w prawo ... całkowicie w prawo;) – BalusC

+0

Dziękuję bardzo! To oszczędzało mnie przed manipulacjami ciągów itp.! – guerda

+1

Dobre połączenie z BeanUtils Apache'a. Sprawia, że ​​pobieranie/ustawianie właściwości jest łatwiejsze i obsługuje konwersję typu. –

4

Konwencja nazewnictwa jest częścią ugruntowanej specyfikacji JavaBeans i jest obsługiwany przez klasy w pakiecie java.beans.

15

Można użyć Reflections ramy tego

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

Można powołać się odbić, a także ustawić kolejność sekwencji dla getter dla wartości poprzez adnotacje

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

}

Output kiedy sortowane

getId Pos: 1 Value: 001 
getName Pos: 2 Value: Anand 
getGender Pos: 3 Value: Male 
getGrade Pos: 4 Value: A 
Powiązane problemy