Comment faire une boucle sur les attributs D'une classe en Java?

Comment puis-je faire une boucle sur les attributs d'une classe en java dynamiquement.

Pour par exemple:

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

}

Est-ce possible en Java?

64
demandé sur Zakaria 2010-07-26 14:25:20

7 réponses

Il n'y a pas de support linguistique pour faire ce que vous demandez.

Vous pouvez accéder de manière réflective aux membres d'un type au moment de l'exécution en utilisant la réflexion (par exemple avec Class.getDeclaredFields() pour obtenir un tableau de Field), mais selon ce que vous essayez de faire, cela peut ne pas être la meilleure solution.

Voir aussi

Connexes questions


Exemple

Voici un exemple simple pour montrer seulement une partie de ce que reflection est capable de faire.

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

L'extrait ci-dessus utilise la réflexion pour inspecter tous les champs déclarés de class String; il produit la sortie suivante:

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, article 53: préférer les interfaces à la réflexion

Ce sont des extraits du livre:

Donné un Class objet, vous pouvez obtenir Constructor, Method, et Field les instances représentant les constructeurs, les méthodes et les champs de la classe. [Ils] vous permettent de manipuler leurs homologues sous-jacents de manière réflective . Ce pouvoir, cependant, vient à un prix:

  • vous perdez tous les avantages de la vérification à la compilation.
  • le code requis pour effectuer un accès réfléchissant est maladroit et verbeux.
  • la Performance en souffre.

En règle générale, les objets ne doivent pas être accessibles de manière réflective dans les applications normales au moment de l'exécution.

Il y a quelques applications sophistiquées qui nécessitent une réflexion. Les exemples incluent [...omis à dessein...] Si vous avez des doutes quant à savoir si votre l'application tombe dans l'une de ces catégories, ce n'est probablement pas le cas.

83
répondu polygenelubricants 2017-05-23 12:18:17

Accéder directement aux champs n'est pas vraiment un bon style en java. Je suggère de créer des méthodes getter et setter pour les champs de votre bean, puis d'utiliser ensuite les classes Introspector et BeanInfo de java.haricots paquet.

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);
}
39
répondu Jörn Horstmann 2010-07-26 11:03:21

Bien que je sois d'accord avec la réponse de Jörn si votre classe est conforme à la spécification JavaBeabs, voici une bonne alternative si ce n'est pas le cas et que vous utilisez Spring.

Spring a une classe nommée ReflectionUtils {[3] } qui offre des fonctionnalités très puissantes, y compris doWithFields (class, callback) , une méthode de style visiteur qui vous permet d'itérer sur un champs de classes en utilisant un objet de rappel comme ceci:

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

    });
}

Mais voici un avertissement: la classe est étiquetée comme " pour interne utiliser uniquement", ce qui est dommage si vous me demandez

16
répondu Sean Patrick Floyd 2017-12-02 01:21:49

Moyen Simple d'itérer sur les champs de classe et d'obtenir des valeurs à partir de l'objet:

 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) {
      }
 }
9
répondu Rickey 2013-01-01 20:52:12

Java a une réflexion (java.réflexion.* ), mais je suggère de regarder dans une bibliothèque comme Apache Beanutils, cela rendra le processus beaucoup moins Poilu que d'utiliser la réflexion directement.

5
répondu Tassos Bassoukos 2010-07-26 10:26:37

Vous pouvez boucler les attributs de classe dynamiquement en utilisant 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);
2
répondu Rehan 2016-06-24 08:43:04

Voici une solution qui trie les propriétés par ordre alphabétique et les imprime toutes avec leurs valeurs:

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());
}
0
répondu Benny Neugebauer 2014-06-10 23:44:31