:: Enseignements :: Master :: M1 :: 2009-2010 :: Java Avancé ::
![[LOGO]](http://igm.univ-mlv.fr/ens/resources/mlv.png) | Réflexion & annotations |
Vous trouverez
ici
quelques notes concernant ce td.
Exercice 1 - Affichage d'un graphe cyclique
Soit la classe suivante, représentant des graphes orientés
avec un noeud initial:
On souhaite créer un graphe sachant que le noeud n1 possède
deux fils n2 et n3, que le noeud n2 possède un fils n4, que
le noeud n4 possède des arcs vers les noeuds n1, n3 et n5 et
que n5 possède un lien sur lui-même.
-
Dessiner le graphe correspondant (sur une feuille de
papier).
- Ecrire le code de création du graphe.
-
On souhaite écrire une méthode
toString()
dont l'affichage indique le noeud initial, puis une
ligne par noeud du graphe, chaque ligne contenant un
identificateur pour le noeud suivi de deux points et des
noeuds vers lesquels il possède un arc.
Noeud initial : n1
n1: n2 n3
n2: n4
n3:
n4: n3 n1 n5
n5: n5
Quel est le parcours de graphe utilisé ?
Quel est la structure de données que l'on doit utiliser
pour réaliser ce parcours. A quel interface cela
correspond en Java ? Quel implantation choisir ?
Réaliser l'implantation de
toString()
.
-
Que se passe-t'il s'il y a un cycle ?
Modifier le code sans changer le classe
Node
.
Exercice 2 - Annotation
-
Déclarer une annotation @Marked avec un attribut de type int appelé level
dont la valeur par défaut est 2.
L'annotation devra être positionnable sur les champs ou les méthodes.
Écrire une fonction void printMarked(int level)
qui affiche l'ensemble des champs et méthodes même les pas visibles)
annotés par une annotation @Marked dont l'attribut level est au moins
level.
-
Modifier votre fonction printMarked pour qu'elle affiche également les champs
et méthodes marqués hérités.
-
Déclarer une annotation Print tel que pour un objet
-
Si un champs est marqué Print ou Print(true) alors le champs est affiché
si c'est un type primitif ou String
-
Si un champs est marqué Print ou Print(true) et
si son type est autre alors l'ensemble des champs de l'objet est
récusivement affiché.
-
Si un champs est marqué Print(false) ou n'est pas marqué par Print
alors le champs est ni affiché ni parcouru récursivement.
L'annotation ne doit être positionnable que sur les champs.
-
Écrire une fonction deepPrint(Object o)
qui affiche récursivement les champs de l'objet en utilisant
l'annotation Print.
Attention aux cycles.
Exercice 3 - Bidouillage des itérateurs d'ArrayList
-
En utilisant les mécanismes de réflexion offerts par le paquetage
java.lang.reflect, modifiez la valeur du champ start du graph de l'exercice 1.
-
Les itérateurs obtenus à partir des collections du paquetage java.util
sont dits fail-fast, ce qui signifie qu'une modification de la structure itérée entrelacée avec
l'utilisation de l'itérateur provoque par cette dernière la levée d'une ConcurrentModificationException
. Pour contrôler ces modifications, les itérateurs utilisent le champ modCount
protégé de la classe abstraite AbstractList.
Pour vous en convaincre, vous pouvez
regarder le code source avec eclipse (ctrl + clic).
Faites en sorte que, dans le cas
particulier l'exemple suivant, l'exception ConcurrentModificationException
ne soit pas levée par l'itérateur d'un ArrayList, malgré la modification
faite sur cette structure. Pour celà, vous devrez modifier par réflexion la valeur du champ
modCount de la liste.
Exercice 4 - Chargeur de classes prolixe
-
On cherche à écrire un classloader affichant les classes
chargées en utilisant les classes de l'exercice 1.
Pour cela, redéfinissez la méthode
loadClass
afin que la méthode affiche les classes chargées.
-
Appeler par réflexion la méthode
main
de la classe
Graph
.
-
Expliquer pourquoi le classloader n'affiche pas le
chargement de la classe
Node
?
-
Rappeler la différence entre la méthode
findClass
et
loadClass
de la classe
ClassLoader
.
Corrigé votre code en conséquence.
-
Voici le code pour charger une classe sur le disque, en
fait il marche pour les classes chargées à partir de
n'importe quel URL. On récupère l'URL en utilisant la
méthode
getResource(String)
.
Modifier votre classloader pour qu'il charge lui-même
les classes de l'exercice 1 en changeant
loadClass
.
Attention, vérifier que vous ne chargez pas plusieurs
fois la même classe. De plus, les classes du boot
classpath (par exemple
java.lang.String
) ne peuvent pas être chargé par un autre
ClassLoader
que le
ClassLoader
primordiale.
© Université de Marne-la-Vallée