В чем разница между getFields и getDeclaredFields в отражении Java
Я немного запутался в разнице между getFields способ и getDeclaredFields метод при использовании отражения Java.
Я читал, что getDeclaredFields дает вам доступ ко всем полям класса и getFields возвращает только открытые поля. Если это так, почему бы вам просто не использовать getDeclaredFields?
может ли кто-нибудь подробно остановиться на этом и объяснить разницу между этими двумя методами, и когда/почему вы хотите использовать один над другим?
3 ответов:
все
publicполя вверх по всей иерархии классов.все поля, независимо от их доступности, но только для текущего класса, а не любые базовые классы, которые текущий класс может наследовать.
чтобы получить все поля вверх по иерархии, я написал следующее функция:
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; }The
exclusiveParentкласс предоставляется для предотвращения извлечения полей изObject. Это может бытьnullесли вы хотитеObjectполя.разъяснить
Lists.newArrayListпроисходит от гуавы.обновление
к вашему сведению, приведенный выше код опубликован на GitHub в my LibEx на ReflectionUtils.
как уже упоминалось,
Class.getDeclaredField(String)только смотрит на поля изClassв котором вы его называете.если вы хотите найти a
FieldнаClassиерархии, вы можете использовать эту простую функцию:/** * 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; }это полезно, чтобы найти
privateполе из суперкласса, например. Кроме того, если вы хотите изменить его значение, вы можете использовать его следующим образом:/** * 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); }
public Field[] getFields() throws SecurityExceptionвозвращает массив, содержащий объекты, поля, отражающие все доступные публичные поля класса или интерфейса, представленного этим Class объект. Элементы в возвращенном массиве не сортируются и не находятся в каком-либо определенном порядке. Этот метод возвращает массив длины 0, если класс или интерфейс не имеет доступных открытых полей или если он представляет класс массива, примитивный тип или void.
в частности, если этот объект класса представляет собой класс, Этот метод возвращает открытые поля этого класса и всех его суперклассов. если этот объект класса представляет интерфейс, этот метод возвращает поля этого интерфейса и всех его суперинтерфейсов.
неявное поле длины для класса массива не отражается этим методом. Пользовательский код должен использовать методы класса Array для манипулирования матрицы.
public Field[] getDeclaredFields() throws SecurityExceptionвозвращает массив объектов поля, отражающих все поля, объявленные в классе или интерфейса, представленного этим Class объект. Это включает в себя открытый, защищенный, доступ по умолчанию (пакет) и частный поля, но исключает наследованные поля. Элементы в возвращенном массиве не сортируются и не находятся в каком-либо конкретном порядок. Этот метод возвращает массив длины 0, если класс или интерфейс не объявляет никаких полей, или если этот объект класса представляет примитивный тип, класс массива или void.
а если мне нужны все поля из всех родительских классов? Необходим некоторый код, например от 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; }
Comments