Рефлексія Java отримує всі приватні поля


76

Цікаво, чи є спосіб отримати усі приватні поля певного класу в Java та їх тип.

Наприклад, припустимо, у мене є клас

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

Тепер я хотів би отримати всі приватні поля ( aaa, bbb, ccc) класу SomeClass(не знаючи назви всіх полів авансом) і перевірити їх тип.


7
@atk Ніхто не змушує вас відповідати; але для багатьох з нас, що покладаються на це питання від Google, головна відповідь - набагато стисліше пояснення, ніж читання довгих публікацій про роздуми. Навіть довгий хвіст таких питань сприяє тому, що сьогодні є СО.
Ангад

Відповіді:


124

Можна отримати всі поля за допомогою методу getDeclaredFields()з Class. Потім вам потрібно перевірити модифікатор кожного поля, щоб знайти приватні:

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

Зверніть увагу, що getDeclaredFields()успадковані поля не повернуть.

Врешті-решт ви отримуєте тип полів методом Field.getType () .


Я думаю, що той факт, що я працюю проти скомпільованого класу, робить його досить незручним, оскільки повернуті поля мають імена типу m0, m1і т.д., і мають тип java.lang.reflect.Method. Це могло бути пов’язано з тим, що я намагався використати роздуми про Spring Bean, відлитий до інтерфейсу?
payne

13

За допомогою цього Modifierможна визначити, чи є поле приватним. Обов’язково використовуйте getDeclaredFieldsметод, щоб гарантувати отримання приватних полів із класу, виклик getFieldsповерне лише загальнодоступні поля.

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

2
@AfzaalAhmadZeeshan, чому ти змінив мою редагування "clazz" на "class", коли нам явно потрібно використовувати змінну "clazz", а не ключове слово "class"
vallentin

Вибачте за цю помилку, я вважав, що це помилка, оскільки ніде не було змінної, пов'язаної з документом або кодом! Вибачте за це ..
Афзаал Ахмад Зеешан

3
@AfzaalAhmadZeeshan була змінна, вона в аргументах методу. Тим не менш, ти хочеш скасувати свої зміни, оскільки я не можу їх змінити?
valentin


8

Використання Java 8:

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

7

Перевірте, чи не є поле приватним

Ви можете відфільтрувати поля за допомогою Modifier.isPrivate :

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

на одному Fieldоб’єкті, який повертається, trueякщо поле єprivate


Зберіть усі поля класу

Щоб зібрати всі поля, використовуйте:

1) Якщо вам потрібні лише поля класу без полів, взятих з ієрархії класів, ви можете просто використовувати:

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

2) Якщо ви не хочете заново винаходити колесо і отримувати всі поля ієрархії класів, ви можете покластись на Apache Commons Lang версії 3.2+, яка передбачає 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));
    }
}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.