4. La classe Field

4.1. Utilisation de Field

La classe Field, comme son nom le laisse supposer, modélise les champs d'une classe. La façon la plus simple d'obtenir un objet de type Field est d'utiliser l'une des méthodes getField() de la classe Class. On peut obtenir ainsi une référence sur tous les champs d'une classe, qu'il soit statique ou non, privé, protégé ou public. La classe Field fonctionne sur le même principe que la classe Class ou Method. Elle permet d'obtenir les informations sur le champ d'une classe.
  • son modificateur de visibilité ;
  • son type ;
  • son nom ;
  • les annotations qu'il porte.
Cette classe permet également de fixer la valeur de ce champ directement, ou de la lire.

4.2. Méthodes disponibles

Les méthodes exposées sont plus simples que celles de la classe Method.
  • getName() : retourne le nom de ce champ.
  • getModifiers() : retourne un entier qui code les modificateurs de ce champ sous forme d'un int. Cet entier peut être décodé grâce à la classe utilitaire Modifier.
  • getDeclaredAnnotations() et getAnnotation(Class) : retourne les annotations portées par ce champ, ou l'annotation dont on passe la classe en paramètre.
  • getInt(Object), getFloat(Object), get(Object)etc... : retournent la valeur de ce champ sous la forme indiquée par le nom de la méthode, pour l'objet passé en paramètre.
  • setInt(Object, int), setFloat(Object, float), setObject(Object, Object)etc... : permettent de fixer la valeur de ce champ sous la forme indiquée par le nom de la méthode, pour l'objet passé en paramètre.

4.3. Accès à un champ par introspection

Voyons comment il est possible de modifier la valeur d'un champ directement, à partir de son nom et du nom de sa classe. On utilise la même classe que celle utilisée pour l'invocation de méthode par introspection.

Exemple 53. Introspection sur un champ

String className =  "org.paumard.test.classe.Marin" ;
String propertyName =  "nom" ;
String value =  "Surcouf" ;

 // jette une ClassNotFoundException
 // on utilise clazz car une variable ne peut pas s'appeler class
Class<?> clazz = Class.forName(className) ;

 // jette IllegalAccessException et InstantiationException
Object o = clazz.newInstance() ;

 // jette NoSuchFieldException
 // attention : getField() ne retourne que les champs publics, ici notre 
 // champ est privé, donc il faut utiliser clazz.getDeclaredField()
Field champNom = clazz.getDeclaredField(propertyName) ;

 // lecture des modificateurs de ce champ
 int mod = champNom.getModifiers() ;
 // on vérifie que notre champ est bien privé
System.out.println("Champ [" + propertyName +  "] privé : " + Modifier.isPrivate(mod)) ;

 // on le rend accessible, pour pouvoir le modifier
 boolean isAccessible = champNom.isAccessible() ;
 if (!isAccessible) {
   champNom.setAccessible(true) ;
}

 // on vérifie que notre champ est toujours privé
 // le rendre accessible ne le modifie pas
mod = champNom.getModifiers() ;
System.out.println("Champ [" + propertyName +  "] privé : " + Modifier.isPrivate(mod)) ;

 // on positionne sa valeur
champNom.set(o, value) ;

 // on remet la propriété accessible à sa valeur 
 // précédente
 if (!isAccessible) {
   champNom.setAccessible(false) ;
}

 // on affiche notre marin
System.out.println(o) ;

L'exécution de ce code donne le résultat suivant.
 Invocation du constructeur vide
 Champ [nom] privé : true
 Champ [nom] privé : true
 Surcouf
On constate donc que :
  • nous avons pu modifier et relire notre champ privé directement, sans passer par ses getters et setters ;
  • positionner la propriété accessible d'un membre ne change pas son modificateur de visibilité !
Cette technique est également utilisée massivement en complément de l'invocation par introspection des setters et getters .
Java API avancées
Retour au blog Java le soir
Cours & Tutoriaux
Table des matières
API Collection
1. Introduction
2. Interface Collection
2.1. Notion de Collection
2.2. Détail des méthodes disponibles
2.3. Interface Iterator
2.4. Implémentation, exemples d'utilisation
3. Interface List
3.1. Notion de List
3.2. Détail des méthodes disponibles
3.3. Interface ListIterator
3.4. Implémentations, exemples d'utilisation
4. Interface Set
4.1. Notion de Set
4.2. Implémentations HashSet et LinkedHashSet
4.3. Exemples d'utilisation
5. Interface SortedSet
5.1. Notion de SortedSet
5.2. Détails des méthodes disponibles
5.3. Exemples d'utilisation
6. Interface NavigableSet
6.1. Notion de NavigableSet
6.2. Détails des méthodes disponibles
6.3. Exemple d'utilisation
7. Interfaces Queue et Deque
7.1. Notion de file d'attente
7.2. Détail des méthodes disponibles
7.3. Utilisation des interfaces Queue et Deque
8. Tables de hachage
8.1. Notion de table de hachage
8.2. Interface Map
8.3. Interface Map.Entry
8.4. Interface SortedMap
8.5. Interface NavigableMap
8.6. Implémentations
8.7. Exemples d'utilisation
9. Classes utilitaires Collections et Arrays
9.1. Introduction
9.2. Classe Arrays
9.3. Classe Collections
Génériques
1. Introduction
2. Un premier exemple
2.1. Une première classe générique
2.2. Une première méthode générique
3. Contraindre un type générique
3.1. Problème posé
3.2. Contraindre un type générique
4. Implémentation des génériques
4.1. Type erasure
4.2. Types génériques et casts
4.3. Type générique et exception
4.4. Construction d'une instance générique
4.5. Génériques et membres statiques
4.6. Collisions de méthodes génériques
4.7. Implémentation de plusieurs types identiques
5. Type <?>
5.1. Introduction
5.2. Type ? extension d'un type
5.3. Type ? super-type d'un type
Expressions régulières
1. Introduction
2. Mise en œuvre des expressions régulières
2.1. Fonctionnement d'une regexp
2.2. Fonctionnement de l'API en Java
2.3. Un premier exemple
2.4. Classe Pattern
2.5. Classe Matcher
2.6. Utilisation des méthode find() et group()
2.7. Méthodes de remplacement
2.8. Sélection de régions
3. Syntaxe des expressions régulières
3.1. Notion de classe
3.2. Étude d'un cas réel
3.3. Recherche d'un mot précis
3.4. Recherche de deux mots précis
3.5. Recherche d'un mot commençant par une lettre donnée
3.6. Cas de mots comportant des caractères accentués
3.7. Recherche sur les lignes
Introspection
1. Introduction
2. La classe Class
2.1. Utilisation de Class
2.2. Méthodes disponibles
2.3. Remarque sur la propriété Accessible
2.4. Type d'une classe
2.5. Création d'une instance à partir d'un objet Class
2.6. Cas des énumérations
3. Les classes Method et Constructor
3.1. Utilisation de Method
3.2. Utilisation de Constructor
3.3. Méthodes disponibles
3.4. Invocation d'une méthode par introspection
4. La classe Field
4.1. Utilisation de Field
4.2. Méthodes disponibles
4.3. Accès à un champ par introspection
5. La classe Modifier
Programmation concurrente
1. Introduction
2. Lançons nos premiers threads
2.1. Introduction
2.2. Un premier thread, extension de Thread
2.3. Un deuxième thread, implémentation de Runnable
2.4. Remarque sur la méthode Thread.sleep(long)
2.5. Arrêter un thread
3. Concurrence d'accès
3.1. Notion d'état
3.2. Exemple de concurrence d'accès sur un état
3.3. Analyse de la concurrence d'accès
3.4. Solution au problème
3.5. Champs volatile
4. Synchronisation
4.1. Définition d'un bloc synchronisé
4.2. Fonctionnement d'un bloc synchronisé
4.3. Notion de deadlock
4.4. Bonnes pratiques pour la synchronisation de threads
5. Opérations atomiques
5.1. Atomicité d'une opération
5.2. Solutions disponibles
5.3. Variables atomiques
6. Collections synchronisées et concurrentes
6.1. Introduction
6.2. Position du problème
6.3. Solutions proposées
7. Files d'attente
7.1. Introduction, pattern producteur / consommateur
7.2. Interface BlockingQueue<E>
7.3. Implémentations de BlockingQueue
7.4. Exemple de producteur / consommateur
7.5. Arrêter un producteur / consommateur : pilule empoisonnée
8. Classes utilitaires de l'API Concurrent
8.1. Introduction
8.2. Énumération TimeUnit
8.3. Interface Callable<V>
8.4. Interfaces Future<V> et RunnableFuture<V>
8.5. Interface ScheduledFuture<V> et RunnableScheduledFuture<V>
9. Pattern executor
9.1. Notion de réserve de threads
9.2. Interface Executor
9.3. Interface ExecutorService
9.4. Interface ScheduledExecutorService
9.5. Classe Executors
9.6. Pattern de lancement de tâches
10. Classes de contrôle d'accès
10.1. Introduction
10.2. Interfaces Lock et ReadWriteLock
10.3. Notion de verrou réentrant
10.4. Classe RentrantLock
10.5. Classe ReadWriteRentrantLock
11. Sémaphores, barrières et latches
11.1. Introduction
11.2. Notion de sémaphore, classe Semaphore
11.3. Notion de latch, classe CountDownLatch
11.4. Notion de barrière, classe CyclicBarrier