Java Reflection erhält alle privaten Felder

76

Ich frage mich, ob es eine Möglichkeit gibt, alle privaten Felder einer Klasse in Java und deren Typ zu erhalten.

Nehmen wir zum Beispiel an, ich habe eine Klasse

class SomeClass {
    private String aaa;
    private SomeOtherClass bbb;
    private double ccc;
}

Nun würde Ich mag alle privaten Felder erhalten ( aaa, bbb, ccc) der Klasse SomeClass(Ohne Namen aller Felder im Voraus zu wissen) und ihre Art zu überprüfen.

user2152361
quelle
7
@atk Niemand zwingt dich zu antworten; Für viele von uns, die auf diese Frage von Google stoßen, ist die beste Antwort eine weitaus prägnantere Erklärung als das Lesen langer Beiträge zum Thema Nachdenken. Sogar die langen Fragen wie diese tragen dazu bei, was SO heute ist.
Angad

Antworten:

123

Es ist möglich, alle Felder mit der Methode getDeclaredFields()von zu erhalten Class. Dann müssen Sie den Modifikator jedes Felds überprüfen, um die privaten zu finden:

List<Field> privateFields = new ArrayList<>();
Field[] allFields = SomeClass.class.getDeclaredFields();
for (Field field : allFields) {
    if (Modifier.isPrivate(field.getModifiers())) {
        privateFields.add(field);
    }
}

Beachten Sie, dass getDeclaredFields()keine geerbten Felder zurückgegeben werden.

Schließlich erhalten Sie den Typ der Felder mit der Methode Field.getType () .

Cyrille Ka
quelle
13

Sie können verwenden, Modifierum festzustellen, ob ein Feld privat ist. Stellen Sie sicher, getDeclaredFieldsdass Sie die Methode verwenden, um sicherzustellen, dass Sie private Felder aus der Klasse abrufen. Beim Aufruf getFieldswerden nur die öffentlichen Felder zurückgegeben.

public class SomeClass {

    private String aaa;
    private Date date;
    private double ccc;
    public int notPrivate;

    public static void main(String[] args) {
        List<Field> fields = getPrivateFields(SomeClass.class);
        for(Field field: fields){
            System.out.println(field.getName());
        }
    }

    public static List<Field> getPrivateFields(Class<?> theClass){
        List<Field> privateFields = new ArrayList<Field>();

        Field[] fields = theClass.getDeclaredFields();

        for(Field field:fields){
            if(Modifier.isPrivate(field.getModifiers())){
                privateFields.add(field);
            }
        }
        return privateFields;
    }
}
Kevin Bowersox
quelle
2
@AfzaalAhmadZeeshan warum hast du meine Bearbeitung "clazz" in "class" geändert, wenn wir eindeutig die Variable "clazz" und nicht das Schlüsselwort "class" verwenden müssen
vallentin
Es tut mir leid für diesen Fehler, ich dachte, dies sei ein Fehler, da nirgendwo eine Variable mit dem Dokument oder dem Code verknüpft war! Verzeihen Sie mir das ..
Afzaal Ahmad Zeeshan
3
@AfzaalAhmadZeeshan gab es eine Variable, es ist in den Argumenten der Methode. Möchtest du deine Änderung widerrufen, da ich sie nicht ändern kann?
Vallentin
10

Versuchen Sie es mit FieldUtilsapache commons-lang3:

FieldUtils.getAllFieldsList(Class<?> cls)
Martin Schröder
quelle
8

Verwenden von Java 8:

Field[] fields = String.class.getDeclaredFields();
List<Field> privateFieldList = Arrays.asList(fields).stream().filter(field -> Modifier.isPrivate(field.getModifiers())).collect(
        Collectors.toList());
Sahil Chhabra
quelle
7

Überprüfen Sie, ob ein Feld privat ist

Sie können die Felder mit Modifier.isPrivate filtern :

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
// ...
Field field = null;
// retrieve the field in some way
// ...
Modifier.isPrivate(field.getModifiers())

auf ein einzelnes FieldObjekt, das zurückgibt, truewenn das Feld istprivate


Sammle alle Felder einer Klasse

Um alle Felder zu sammeln, verwenden Sie:

1) Wenn Sie nur die Felder der Klasse ohne die Felder aus der Klassenhierarchie benötigen, können Sie einfach Folgendes verwenden:

Field[] fields = SomeClass.class.getDeclaredFields();

2) Wenn Sie das Rad nicht neu erfinden und alle Felder einer Klassenhierarchie abrufen möchten, können Sie sich auf Apache Commons Lang Version 3.2+ verlassen, die Folgendes bietet FieldUtils.getAllFieldsList:

import java.lang.reflect.Field;
import java.util.AbstractCollection;
import java.util.AbstractList;
import java.util.AbstractSequentialList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.lang3.reflect.FieldUtils;
import org.junit.Assert;
import org.junit.Test;

public class FieldUtilsTest {

    @Test
    public void testGetAllFieldsList() {

        // Get all fields in this class and all of its parents
        final List<Field> allFields = FieldUtils.getAllFieldsList(LinkedList.class);

        // Get the fields form each individual class in the type's hierarchy
        final List<Field> allFieldsClass = Arrays.asList(LinkedList.class.getFields());
        final List<Field> allFieldsParent = Arrays.asList(AbstractSequentialList.class.getFields());
        final List<Field> allFieldsParentsParent = Arrays.asList(AbstractList.class.getFields());
        final List<Field> allFieldsParentsParentsParent = Arrays.asList(AbstractCollection.class.getFields());

        // Test that `getAllFieldsList` did truly get all of the fields of the the class and all its parents 
        Assert.assertTrue(allFields.containsAll(allFieldsClass));
        Assert.assertTrue(allFields.containsAll(allFieldsParent));
        Assert.assertTrue(allFields.containsAll(allFieldsParentsParent));
        Assert.assertTrue(allFields.containsAll(allFieldsParentsParentsParent));
    }
}
Madx
quelle
5

Meinst du wie

Field[] fields = SomeClass.class.getDeclaredFields();
Peter Lawrey
quelle
2
Dies schließt alle geerbten Felder aus.
Martin Schröder