:: Enseignements :: ESIPE :: E4INFO :: 2010-2011 :: Java Avancé ::
![[LOGO]](http://igm.univ-mlv.fr/ens/resources/mlv.png) | Réflexion et 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.
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() .
-
Après avoir pris en compte la possible présence de cycle, précisez quelle est la limitation
majeure de votre implémentation (logique dans le cadre de la théorie des graphes mais pas dans
celle de Java) ?
Modifier votre code pour y remédier 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 chargeur de classe 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