Es gibt keine sprachliche Unterstützung, um das zu tun, wonach Sie fragen.
Sie können zur Laufzeit reflektierend auf die Mitglieder eines Typs zugreifen, indem Sie Reflection verwenden (z. B. Class.getDeclaredFields()
um ein Array von zu erhalten Field
). Je nachdem, was Sie tun möchten, ist dies möglicherweise nicht die beste Lösung.
Siehe auch
Verwandte Fragen
Beispiel
Hier ist ein einfaches Beispiel, um nur einen Teil dessen zu zeigen, wozu Reflexion in der Lage ist.
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()
);
}
}
}
Das obige Snippet verwendet Reflexion, um alle deklarierten Felder von zu untersuchen class String
. es erzeugt die folgende Ausgabe:
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
Effektive Java 2nd Edition, Punkt 53: Schnittstellen der Reflexion vorziehen
Dies sind Auszüge aus dem Buch:
Bei einem Class
Objekt können Sie erhalten Constructor
, Method
und Field
Instanzen , die die Konstrukteure, Methoden und Felder der Klasse. Mit [Sie] können Sie die zugrunde liegenden Gegenstücke reflektierend manipulieren . Diese Kraft hat jedoch ihren Preis:
- Sie verlieren alle Vorteile der Überprüfung zur Kompilierungszeit.
- Der Code, der für den reflektierenden Zugriff erforderlich ist, ist ungeschickt und ausführlich.
- Die Leistung leidet.
In der Regel sollte zur Laufzeit in normalen Anwendungen nicht reflektierend auf Objekte zugegriffen werden.
Es gibt einige anspruchsvolle Anwendungen, die Reflexion erfordern. Beispiele sind [... absichtlich weggelassen ...] Wenn Sie Zweifel haben, ob Ihre Bewerbung in eine dieser Kategorien fällt, ist dies wahrscheinlich nicht der Fall.
Field.get
können Sie die Werte eines Feldes reflektierend lesen. Wenn japrivate
, können Sie das vielleicht umgehensetAccessible
. Ja, Reflexion ist sehr leistungsfähig und ermöglicht es Ihnenprivate
,final
Felder zu inspizieren, Felder zu überschreiben ,private
Konstruktoren aufzurufen usw. Wenn Sie weitere Unterstützung beim Entwurfsaspekt benötigen, sollten Sie wahrscheinlich eine neue Frage mit viel mehr Informationen schreiben. Vielleicht brauchen Sie diese vielen Attribute überhaupt nicht (z. B. useenum
oderList
usw.).static void inspect(Class<?> klazz)
Der direkte Zugriff auf die Felder ist in Java kein wirklich guter Stil. Ich würde vorschlagen, Getter- und Setter-Methoden für die Felder Ihrer Bean zu erstellen und dann die Klassen Introspector und BeanInfo aus dem Paket java.beans zu verwenden.
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); }
quelle
propertyDesc.getReadMethod().getDeclaringClass() != Object.class
oder eine Klasse angeben, um die Analyse als zweiten Parameter zu stoppengetBeanInfo(MyBean.class, Object.class)
.Ich stimme Jörns Antwort zu, wenn Ihre Klasse der JavaBeabs-Spezifikation entspricht, aber hier ist eine gute Alternative, wenn dies nicht der Fall ist und Sie Spring verwenden.
Spring verfügt über eine Klasse namens ReflectionUtils , die einige sehr leistungsstarke Funktionen bietet, darunter doWithFields (Klasse, Rückruf) , eine Methode im Besucherstil, mit der Sie mithilfe eines Rückrufobjekts wie folgt über Klassenfelder iterieren können:
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)); }); }
Aber hier ist eine Warnung: Die Klasse ist als "nur für den internen Gebrauch" gekennzeichnet, was schade ist, wenn Sie mich fragen
quelle
Einfache Möglichkeit, Klassenfelder zu durchlaufen und Werte vom Objekt abzurufen:
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) { } }
quelle
Java hat Reflection (java.reflection. *), Aber ich würde vorschlagen, in eine Bibliothek wie Apache Beanutils zu schauen, da dies den Prozess viel weniger haarig macht als die direkte Verwendung von Reflection.
quelle
Hier ist eine Lösung, die die Eigenschaften alphabetisch sortiert und sie alle zusammen mit ihren Werten druckt:
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()); }
quelle