Jaka jest różnica między getFields i getDeclaredFields w Javie

Jestem trochę zdezorientowany co do różnicy między metodą getFields a metodą getDeclaredFields przy użyciu Java reflection.

Czytałem, że getDeclaredFields daje dostęp do wszystkich pól klasy i że getFields zwraca tylko pola publiczne. Jeśli tak jest, dlaczego nie zawsze używasz getDeclaredFields?

Czy ktoś mógłby to rozwinąć i wyjaśnić różnicę między tymi dwiema metodami i kiedy / dlaczego chciałbyś użyć jednej nad drugą?

Author: Flow, 2013-06-06

3 answers

GetFields()

Wszystkie public Pola w całej hierarchii klas.

GetDeclaredFields()

Wszystkie pola, niezależnie od ich dostępności, ale tylko dla bieżącej klasy, a nie żadnych klas bazowych, od których obecna klasa może być dziedziczona.

Aby uzyskać wszystkie pola w hierarchii, napisałem następującą funkcję:

public static Iterable<Field> getFieldsUpTo(@Nonnull Class<?> startClass, 
                                   @Nullable Class<?> exclusiveParent) {

   List<Field> currentClassFields = Lists.newArrayList(startClass.getDeclaredFields());
   Class<?> parentClass = startClass.getSuperclass();

   if (parentClass != null && 
          (exclusiveParent == null || !(parentClass.equals(exclusiveParent)))) {
     List<Field> parentClassFields = 
         (List<Field>) getFieldsUpTo(parentClass, exclusiveParent);
     currentClassFields.addAll(parentClassFields);
   }

   return currentClassFields;
}

Klasa exclusiveParent jest zapewniona, aby zapobiec pobieraniu pól z Object. Może to być null, Jeśli chcesz pola Object.

Dla wyjaśnienia, Lists.newArrayList pochodzi z guawy.

Update

FYI, powyższy kod jest opublikowany na Githubie w moim projekcie LibEx W ReflectionUtils .

 198
Author: John B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-15 06:08:07

Jak już wspomniano, Class.getDeclaredField(String) patrzy tylko na pola z Class, w których je wywołujesz.

Jeśli chcesz wyszukać Field w hierarchii Class, możesz użyć tej prostej funkcji:

/**
 * Returns the first {@link Field} in the hierarchy for the specified name
 */
public static Field getField(Class<?> clazz, String name) {
    Field field = null;
    while (clazz != null && field == null) {
        try {
            field = clazz.getDeclaredField(name);
        } catch (Exception e) {
        }
        clazz = clazz.getSuperclass();
    }
    return field;
}

Jest to przydatne, aby znaleźć pole private z klasy nadrzędnej, na przykład. Ponadto, jeśli chcesz zmodyfikować jego wartość, możesz użyć go w następujący sposób:

/**
 * Sets {@code value} to the first {@link Field} in the {@code object} hierarchy, for the specified name
 */
public static void setField(Object object, String fieldName, Object value) throws Exception {
    Field field = getField(object.getClass(), fieldName);
    field.setAccessible(true);
    field.set(object, value);
}
 5
Author: IvanRF,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-19 20:15:17

public Field[] getFields() throws SecurityException

Zwraca tablicę zawierającą Obiekty pola odzwierciedlające wszystkie Dostępne pola publiczne klasy lub interfejsu reprezentowanego przez ten obiekt klasy. Zwracane elementy tablicy nie są sortowane i nie są w żadnej określonej kolejności. Metoda zwraca tablicę o długości 0, jeśli klasa lub interfejs nie ma dostępnych publicznych pól, lub jeśli reprezentuje klasę tablicy, Typ prymitywny lub void.

W szczególności, jeśli obiekt tej klasy reprezentuje klasy, ta metoda zwraca publiczne pola tej klasy i wszystkich jej superklas. Jeśli obiekt tej klasy reprezentuje interfejs, metoda ta zwraca pola tego interfejsu i wszystkich jego superinterfejsów.

Domyślne pole długości dla klasy array nie jest odzwierciedlane przez tę metodę. Kod użytkownika powinien używać metod tablicy klas do manipulowania tablicami.


public Field[] getDeclaredFields() throws SecurityException

Zwraca tablicę obiektów pola odzwierciedlającą wszystkie pola zadeklarowane przez klasę lub interfejs reprezentowany przez ten obiekt klasy. To obejmuje publiczny, chroniony, domyślny (pakiet) dostęp i prywatny pola, ale nie obejmuje dziedziczenia pola. Zwracane elementy tablicy nie są sortowane i nie są w żadnej określonej kolejności. Metoda ta zwraca tablicę o długości 0, jeśli klasa lub interfejs nie deklaruje żadnych pól, lub jeśli obiekt tej klasy reprezentuje typ prymitywny, klasę tablicy lub pustka.


A co jeśli potrzebuję wszystkich pól ze wszystkich klas nadrzędnych? Potrzebny jest jakiś kod, np. z https://stackoverflow.com/a/35103361/755804 :

public static List<Field> getAllModelFields(Class aClass) {
    List<Field> fields = new ArrayList<>();
    do {
        Collections.addAll(fields, aClass.getDeclaredFields());
        aClass = aClass.getSuperclass();
    } while (aClass != null);
    return fields;
}
 4
Author: 18446744073709551615,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:13