web-dev-qa-db-fra.com

Obtenir tous les champs (même privés et hérités) de la classe

Je fais un projet universitaire.
Je dois obtenir tous les champs de la classe. Même privé et hérité. J'ai essayé d'obtenir tous les champs déclarés, puis de lancer en super classe et de répéter. Fragment de mon code:

private void listAllFields(Object obj) {
    List<Field> fieldList = new ArrayList<Field>();
    while (obj != null) {
        fieldList.addAll(Arrays.asList(obj.getClass().getDeclaredFields()));
        obj = obj.getClass().getSuperclass().cast(obj);
    }
    // rest of code

Mais ça ne marche pas. tmpObj après la conversion est toujours la même classe (pas la superclasse).
J'apprécierai toute aide pour résoudre un problème de casting ou pour récupérer ces champs de manière différente.

Le problème n'est pas d'accéder aux champs, mais d'obtenir les noms des champs!
Je le gère comme suit:

private void listAllFields(Object obj) {
    List<Field> fieldList = new ArrayList<Field>();
    Class tmpClass = obj.getClass();
    while (tmpClass != null) {
        fieldList.addAll(Arrays.asList(tmpClass .getDeclaredFields()));
        tmpClass = tmpClass .getSuperclass();
    }
    // rest of code
49
Michał Herman
obj = obj.getClass().getSuperclass().cast(obj);

Cette ligne ne fait pas ce que vous attendez d'elle. Lancer un Object ne le change pas, il indique simplement au compilateur de le traiter comme autre chose.

Par exemple. vous pouvez convertir un List en un Collection, mais il restera toujours un List.

Cependant, boucler à travers les super-classes pour accéder aux champs fonctionne bien sans transtypage:

Class<?> current = yourClass;
while(current.getSuperclass()!=null){ // we don't want to process Object.class
    // do something with current's fields
    current = current.getSuperclass();
}

En passant, si vous avez accès au framework Spring, il existe une méthode pratique pour parcourir en boucle les champs d'une classe et de toutes les super classes:
ReflectionUtils.doWithFields(baseClass, FieldCallback)
(voir aussi ma réponse précédente: Accès aux champs hérités privés via une réflexion en Java )

78
Sean Patrick Floyd

getDeclaredFields() vous donne tous les champs de cette classe, y compris ceux de private.

getFields() vous donne tous les champs public de cette classe ET ses super-classes.

Si vous voulez private/protected méthodes de super classes, vous devrez appeler à plusieurs reprises getSuperclass() puis appelez getDeclaredFields() sur l'objet Super Class.

Rien ici n’est clairement expliqué dans le javadocs

32
Tom McIntyre

Voici la méthode que j'utilise pour obtenir tous les champs d'un objet

private <T> List<Field> getFields(T t) {
        List<Field> fields = new ArrayList<>();
        Class clazz = t.getClass();
        while (clazz != Object.class) {
            fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
            clazz = clazz.getSuperclass();
        }
        return fields;
    }
9
Adelin

essayez ces

Comment lire un champ privé en Java?

Est-il possible dans Java d'accéder aux champs privés via réflexion

Field.setAccessible (true) est ce que vous devez faire pour le rendre accessible par réflexion.

import Java.lang.reflect.Field;

class B 
{
    private int i = 5;
}

public class A extends B 
{
    public static void main(String[] args) throws Exception 
    {
        A a = new A();
        Field[] fs = a.getClass().getSuperclass().getDeclaredFields();
        for (Field field : fs)
        {
            field.setAccessible(true);
            System.out.println( field.get( a ) );
        }
    }
}
3
gurvinder372
ClassName obj  =  new ClassName();
Field field  =   ClassName.class.getDeclaredField  ("name of the field");
field.setAccessible   (true);
DataType value  =  (DataType) field.get  (obj);

Vous devez utiliser setAccessible à true avant d'extraire la valeur. Parfois, la machine virtuelle Java ne permet pas d’extraire la variable privée, elle peut donner une exception de sécurité.

1
Yatin Wadhawan

Auparavant demandé.

Accès aux champs hérités privés via une réflexion en Java

Dans votre code, définissez field.setAccessible(true);

1
Maximin

Pour obtenir des champs de superclasse, utilisez getSuperclass(). De là, vous pouvez obtenir des champs de superclasse.

1
Vineet Singla

Cette solution utilise des flux Java 8, utiles pour ceux qui apprennent la programmation fonctionnelle en Java. Elle effectue une itération sur getSuperclass et getDeclaredFields comme indiqué dans les autres réponses, mais de manière fonctionnelle.

La ligne suivante affichera le nom de chaque nom de champ trouvé sur SomeClass ou l’une de ses superclasses.

allFieldsFor(SomeClass.class).map(Field::getName).forEach(System.out::println);

Voici le code qui parcourt les superclasses pour créer le flux de champs.

private Stream<Field> allFieldsFor( Class c ) {
    return walkInheritanceTreeFor(c).flatMap( k -> Arrays.stream(k.getDeclaredFields()) );
}

private Stream<Class> walkInheritanceTreeFor( Class c ) {
    return iterate( c, k -> Optional.ofNullable(k.getSuperclass()) );
}

La méthode suivante est modélisée à partir de Streams.iterate. Cependant, Streams.iterate est conçu pour créer des flux infinis. Cette version a été modifiée pour se terminer lorsque Optional.none () est renvoyé par fetchNextFunction.

private <T> Stream<T> iterate( T seed, Function<T,Optional<T>> fetchNextFunction ) {
    Objects.requireNonNull(fetchNextFunction);

    Iterator<T> iterator = new Iterator<T>() {
        private Optional<T> t = Optional.ofNullable(seed);

        public boolean hasNext() {
            return t.isPresent();
        }

        public T next() {
            T v = t.get();

            t = fetchNextFunction.apply(v);

            return v;
        }
    };

    return StreamSupport.stream(
        Spliterators.spliteratorUnknownSize( iterator, Spliterator.ORDERED | Spliterator.IMMUTABLE),
        false
    );
}
1
Chris K

Oui, il est possible d’utiliser Reflection.

Dans votre code, définissez Field.setAccessible(true);

Allez-y et apprenez le concept mais NE LE FAITES PAS :-)

1
Geek