Je suis un peu confus quant à la différence entre la méthode getFields
et la méthode getDeclaredFields
lorsque vous utilisez Java reflet.
J'ai lu que getDeclaredFields
vous donne accès à tous les champs de la classe et que getFields
ne renvoie que des champs publics. Si tel est le cas, pourquoi ne pas simplement utiliser getDeclaredFields
?
Quelqu'un peut-il développer cette idée et expliquer la différence entre les deux méthodes, et quand/pourquoi voudriez-vous utiliser l'une plutôt que l'autre?
Tous les public
champs de la hiérarchie de classe entière.
Tous les champs, quelle que soit leur accessibilité, mais uniquement pour la classe actuelle, pas les classes de base dont la classe actuelle pourrait hériter.
Pour obtenir tous les champs dans la hiérarchie, j'ai écrit la fonction suivante:
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;
}
La classe exclusiveParent
permet d'empêcher l'extraction des champs de Object
. Ce peut être null
si vous voulez les champs Object
.
Pour clarifier, Lists.newArrayList
vient de Guava.
Pour votre information, le code ci-dessus est publié sur GitHub dans mon LibEx projet dans ReflectionUtils .
Comme déjà mentionné, Class.getDeclaredField(String)
ne regarde que les champs de la Class
dans laquelle vous l'appelez.
Si vous souhaitez rechercher un Field
dans la hiérarchie Class
, vous pouvez utiliser cette fonction simple:
/**
* 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;
}
Ceci est utile pour trouver un champ private
d'une super-classe, par exemple. En outre, si vous souhaitez modifier sa valeur, vous pouvez l'utiliser comme suit:
/**
* 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
Renvoie un tableau contenant des objets Field reflétant tous les () champs publics accessibles de la classe ou de l'interface représentée par celui-ci. Objet de classe. Les éléments du tableau renvoyé ne sont pas triés et ne sont dans aucun ordre particulier. Cette méthode retourne un tableau de longueur 0 si la classe ou l'interface n'a pas de champs publics accessibles, ou si elle représente une classe de tableau, un type primitif ou void.
Plus précisément, si cet objet Class représente une classe, cette méthode retourne les champs publics de cette classe et de toutes ses superclasses. Si cet objet Class représente une interface, cette méthode renvoie les champs de cette interface et de toutes ses superinterfaces.
Le champ de longueur implicite pour la classe array n'est pas reflété par cette méthode. Le code utilisateur doit utiliser les méthodes de la classe Array pour manipuler des tableaux.
public Field[] getDeclaredFields() throws SecurityException
Retourne un tableau d'objets Field reflétant tous les champs déclarés par la classe ou l'interface représentée par cette classe. objet. Ce inclut les champs public, protégé, par défaut (paquet) et privé , mais exclut les champs hérités . Les éléments du tableau renvoyé ne sont pas triés et ne sont dans aucun ordre particulier. Cette méthode retourne un tableau de longueur 0 si la classe ou l'interface ne déclare aucun champ ou si cet objet Class représente un type primitif, une classe de tableau ou void.
Et si j'ai besoin de tous les champs de toutes les classes parentes? Un peu de code est nécessaire, par exemple. de 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;
}