Nie ma wsparcia językowego, aby zrobić to, o co prosisz.
Możesz w sposób refleksyjny uzyskiwać dostęp do elementów członkowskich typu w czasie wykonywania za pomocą refleksji (np. Za pomocą, Class.getDeclaredFields()
aby uzyskać tablicę Field
), ale w zależności od tego, co próbujesz zrobić, może to nie być najlepsze rozwiązanie.
Zobacz też
Powiązane pytania
Przykład
Oto prosty przykład, który pokazuje tylko część tego, do czego zdolna jest refleksja.
import java.lang.reflect.*;
public class DumpFields {
public static void main(String[] args) {
inspect(String.class);
}
static <T> void inspect(Class<T> klazz) {
Field[] fields = klazz.getDeclaredFields();
System.out.printf("%d fields:%n", fields.length);
for (Field field : fields) {
System.out.printf("%s %s %s%n",
Modifier.toString(field.getModifiers()),
field.getType().getSimpleName(),
field.getName()
);
}
}
}
Powyższy fragment wykorzystuje odbicie, aby sprawdzić wszystkie zadeklarowane pola class String
; generuje następujący wynik:
7 fields:
private final char[] value
private final int offset
private final int count
private int hash
private static final long serialVersionUID
private static final ObjectStreamField[] serialPersistentFields
public static final Comparator CASE_INSENSITIVE_ORDER
Efektywna Java 2. wydanie, pozycja 53: Preferuj interfejsy do refleksji
Oto fragmenty książki:
Mając Class
obiekt, możesz uzyskać Constructor
, Method
i Field
instancje reprezentujące konstruktory, metody i pola tej klasy. [Umożliwiają] refleksyjną manipulację ich podstawowymi odpowiednikami . Ta moc ma jednak swoją cenę:
- Utracisz wszystkie korzyści płynące ze sprawdzania w czasie kompilacji.
- Kod wymagany do wykonania refleksyjnego dostępu jest niezgrabny i rozwlekły.
- Cierpi na tym wydajność.
Z reguły dostęp do obiektów nie powinien być odzwierciedlany w normalnych aplikacjach w czasie wykonywania.
Istnieje kilka wyrafinowanych aplikacji, które wymagają refleksji. Przykłady obejmują [... celowo pominięte ...] Jeśli masz jakiekolwiek wątpliwości, czy Twoje zgłoszenie należy do jednej z tych kategorii, prawdopodobnie tak nie jest.
Field.get
, czego możesz użyć do refleksyjnego odczytywania wartości pola. Jeśli takprivate
, możesz to obejśćsetAccessible
. Tak, odbicie jest bardzo potężne i pozwala na takie rzeczy, jak sprawdzanieprivate
pól, nadpisywaniefinal
pól, wywoływanieprivate
konstruktorów itp. Jeśli potrzebujesz dalszej pomocy przy projektowaniu, prawdopodobnie powinieneś napisać nowe pytanie z dużo większą ilością informacji. Być może w pierwszej kolejności nie potrzebujesz tych wielu atrybutów (np. Użyjenum
lubList
itp.).static void inspect(Class<?> klazz)
Bezpośredni dostęp do pól nie jest dobrym stylem w Javie. Sugerowałbym utworzenie metod pobierających i ustawiających dla pól twojego beana, a następnie użycie klas Introspector i BeanInfo z pakietu java.beans.
MyBean bean = new MyBean(); BeanInfo beanInfo = Introspector.getBeanInfo(MyBean.class); for (PropertyDescriptor propertyDesc : beanInfo.getPropertyDescriptors()) { String propertyName = propertyDesc.getName(); Object value = propertyDesc.getReadMethod().invoke(bean); }
źródło
propertyDesc.getReadMethod().getDeclaringClass() != Object.class
lub określić klasę, aby zatrzymać analizę jako drugi parametr, npgetBeanInfo(MyBean.class, Object.class)
.Chociaż zgadzam się z odpowiedzią Jörna, jeśli twoja klasa jest zgodna ze specyfikacją JavaBeabs, tutaj jest dobra alternatywa, jeśli tak nie jest i używasz Spring.
Spring ma klasę o nazwie ReflectionUtils, która oferuje bardzo potężne funkcje, w tym doWithFields (klasa, wywołanie zwrotne) , metodę w stylu gościa, która umożliwia iterację po polach klas przy użyciu obiektu wywołania zwrotnego, takiego jak ten:
public void analyze(Object obj){ ReflectionUtils.doWithFields(obj.getClass(), field -> { System.out.println("Field name: " + field.getName()); field.setAccessible(true); System.out.println("Field value: "+ field.get(obj)); }); }
Ale oto ostrzeżenie: klasa jest oznaczona jako „tylko do użytku wewnętrznego”, a szkoda, jeśli mnie zapytasz
źródło
Prosty sposób na iterację po polach klas i uzyskanie wartości z obiektu:
Class<?> c = obj.getClass(); Field[] fields = c.getDeclaredFields(); Map<String, Object> temp = new HashMap<String, Object>(); for( Field field : fields ){ try { temp.put(field.getName().toString(), field.get(obj)); } catch (IllegalArgumentException e1) { } catch (IllegalAccessException e1) { } }
źródło
Java ma Reflection (java.reflection. *), Ale sugerowałbym zajrzenie do biblioteki takiej jak Apache Beanutils, dzięki czemu proces będzie znacznie mniej skomplikowany niż bezpośrednie użycie odbicia.
źródło
Oto rozwiązanie, które sortuje właściwości alfabetycznie i drukuje je wszystkie wraz z ich wartościami:
public void logProperties() throws IllegalArgumentException, IllegalAccessException { Class<?> aClass = this.getClass(); Field[] declaredFields = aClass.getDeclaredFields(); Map<String, String> logEntries = new HashMap<>(); for (Field field : declaredFields) { field.setAccessible(true); Object[] arguments = new Object[]{ field.getName(), field.getType().getSimpleName(), String.valueOf(field.get(this)) }; String template = "- Property: {0} (Type: {1}, Value: {2})"; String logMessage = System.getProperty("line.separator") + MessageFormat.format(template, arguments); logEntries.put(field.getName(), logMessage); } SortedSet<String> sortedLog = new TreeSet<>(logEntries.keySet()); StringBuilder sb = new StringBuilder("Class properties:"); Iterator<String> it = sortedLog.iterator(); while (it.hasNext()) { String key = it.next(); sb.append(logEntries.get(key)); } System.out.println(sb.toString()); }
źródło