No hay soporte lingüístico para hacer lo que está pidiendo.
Puede acceder de forma reflexiva a los miembros de un tipo en tiempo de ejecución utilizando la reflexión (por ejemplo, con Class.getDeclaredFields()
para obtener una matriz de Field
), pero dependiendo de lo que esté intentando hacer, esta puede no ser la mejor solución.
Ver también
Preguntas relacionadas
Ejemplo
Aquí hay un ejemplo simple para mostrar solo algo de lo que la reflexión es capaz de hacer.
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()
);
}
}
}
El fragmento anterior utiliza la reflexión para inspeccionar todos los campos declarados de class String
; produce la siguiente salida:
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
Effective Java 2nd Edition, Item 53: Preferir interfaces a la reflexión
Estos son extractos del libro:
Dado un Class
objeto, puede obtener Constructor
, Method
y las Field
instancias que representan los constructores, métodos y campos de la clase. [Ellos] le permiten manipular reflexivamente a sus contrapartes subyacentes . Este poder, sin embargo, tiene un precio:
- Pierde todos los beneficios de la verificación en tiempo de compilación.
- El código requerido para realizar el acceso reflexivo es torpe y detallado.
- El rendimiento sufre.
Como regla general, no se debe acceder a los objetos de forma reflexiva en aplicaciones normales en tiempo de ejecución.
Hay algunas aplicaciones sofisticadas que requieren reflexión. Los ejemplos incluyen [... omitido a propósito ...] Si tiene alguna duda sobre si su aplicación cae en una de estas categorías, probablemente no lo haga.
Field.get
que puede utilizar para leer los valores de un campo de forma reflexiva. Si es asíprivate
, es posible que pueda solucionarlosetAccessible
. Sí, la reflexión es muy poderosa y le permite hacer cosas como inspeccionarprivate
campos, sobrescribirfinal
campos, invocarprivate
constructores, etc. Si necesita más ayuda con el aspecto del diseño, probablemente debería escribir una nueva pregunta con mucha más información. Quizás no necesite estos muchos atributos en primer lugar (por ejemplo, useenum
oList
, etc.).static void inspect(Class<?> klazz)
Acceder a los campos directamente no es realmente un buen estilo en Java. Sugeriría crear métodos getter y setter para los campos de su bean y luego usar las clases Introspector y BeanInfo del paquete 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); }
fuente
propertyDesc.getReadMethod().getDeclaringClass() != Object.class
o puede especificar una clase para detener el análisis como el segundo parámetro comogetBeanInfo(MyBean.class, Object.class)
.Si bien estoy de acuerdo con la respuesta de Jörn si su clase se ajusta a la especificación JavaBeabs, aquí hay una buena alternativa si no lo hace y usa Spring.
Spring tiene una clase llamada ReflectionUtils que ofrece una funcionalidad muy poderosa, incluyendo doWithFields (clase, devolución de llamada) , un método de estilo visitante que le permite iterar sobre los campos de una clase usando un objeto de devolución de llamada como este:
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)); }); }
Pero aquí hay una advertencia: la clase está etiquetada como "solo para uso interno", lo cual es una pena si me preguntas
fuente
Una forma sencilla de iterar sobre los campos de clase y obtener valores del objeto:
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) { } }
fuente
Java tiene Reflection (java.reflection. *), Pero sugeriría buscar en una biblioteca como Apache Beanutils, hará que el proceso sea mucho menos complicado que usar la reflexión directamente.
fuente
Aquí hay una solución que ordena las propiedades alfabéticamente y las imprime todas junto con sus valores:
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()); }
fuente