¿Cómo recorrer los atributos de clase en Java?

¿Cómo puedo iterar sobre los atributos de una clase en Java dinámicamente?

Por ejemplo:

public class MyClass { private type1 att1; private type2 att2; ... public void function() { for(var in MyClass.Attributes) { System.out.println(var.class); } } } 

¿Es esto posible en Java?

No hay soporte lingüístico para hacer lo que estás pidiendo.

Puede acceder reflexivamente a los miembros de un tipo en tiempo de ejecución mediante la reflexión (por ejemplo, con Class.getDeclaredFields() para obtener una matriz de Field ), pero dependiendo de lo que esté intentando hacer, puede que esta no sea la mejor solución.

Ver también

  • Tutoriales de Java: Reflection API / Advanced Language Topics: Reflection

Preguntas relacionadas

  • ¿Qué es reflexión y por qué es útil?
  • Reflexión de Java: ¿Por qué es tan malo?
  • ¿Cómo podría la Reflexión no conducir a olores de código?
  • Volcar las propiedades de un objeto java

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  void inspect(Class 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 de arriba usa reflexión para inspeccionar todos los campos declarados de la class String ; produce el siguiente resultado:

 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: Prefiere las interfaces a la reflexión

Estos son extractos del libro:

Dado un objeto Class , puede obtener instancias de Constructor , Method y Field representan los constructores, métodos y campos de la clase. [Ellos] te permiten manipular sus contrapartes subyacentes reflexivamente . Este poder, sin embargo, tiene un precio:

  • Usted pierde todos los beneficios de la verificación en tiempo de comstackción.
  • El código requerido para realizar un acceso reflexivo es torpe y detallado.
  • El rendimiento sufre.

Como regla, no se debe acceder a los objetos de forma reflexiva en las aplicaciones normales durante el 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 pertenece a una de estas categorías, probablemente no lo haga.

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

Si bien estoy de acuerdo con la respuesta de Jörn si su clase cumple con las especificaciones JavaBeabs, aquí hay una buena alternativa si no es así y utiliza Spring.

Spring tiene una clase llamada ReflectionUtils que ofrece algunas funciones muy potentes, incluyendo doWithFields (clase, callback) , un método de estilo de visitante que le permite iterar sobre campos de clases utilizando un objeto de callback 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 lástima si me preguntas

Manera simple de iterar sobre campos de clase y obtener valores de un objeto:

  Class c = obj.getClass(); Field[] fields = c.getDeclaredFields(); Map temp = new HashMap(); for( Field field : fields ){ try { temp.put(field.getName().toString(), field.get(obj)); } catch (IllegalArgumentException e1) { } catch (IllegalAccessException e1) { } } 

Java tiene Reflection (java.reflection. *), Pero sugiero que busque en una biblioteca como Apache Beanutils, hará que el proceso sea menos peludo que utilizando la reflexión directamente.

Puede hacer un bucle de los atributos de la clase de forma dinámica utilizando java Reflections API-

 for (Field field : objClass.getDeclaredFields()) { // Invoke the getter method on the Institution1 object. Object objField = new PropertyDescriptor(field.getName(), Institute1.class).getReadMethod().invoke(inst1); 

Aquí hay una solución que clasifica las propiedades alfabéticamente y las imprime todas juntas con sus valores:

 public void logProperties() throws IllegalArgumentException, IllegalAccessException { Class aClass = this.getClass(); Field[] declaredFields = aClass.getDeclaredFields(); Map 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 sortedLog = new TreeSet<>(logEntries.keySet()); StringBuilder sb = new StringBuilder("Class properties:"); Iterator it = sortedLog.iterator(); while (it.hasNext()) { String key = it.next(); sb.append(logEntries.get(key)); } System.out.println(sb.toString()); }