Corrigé - Département Informatique

Transcription

Corrigé - Département Informatique
UNIVERSITÉ DE NICE – SOPHIA ANTIPOLIS
Master d’informatique 1ère année
UFR FACULTÉ DES SCIENCES
Génie logiciel orienté objet 2006-2007
Parc Valrose – BP 71 – F 06108 NICE Cedex 2
P. Collet, R. Rousseau
Séance de TP n◦ 02 de la semaine du 10 octobre 2006
Réflexivité en Java
Corrigé
Exercice 1 : un analyseur de classes
Ecrivez une programme qui attend qu’on tape au clavier le nom d’une classe puis qui affiche à l’écran, si possible avec une indentation significative, toutes les informations relatives à cette classe. On ne demande que les
membres définis dans la classe,x pas ceux qui sont hérités.
Voici “un exemple d’utilisation” avec la classe Date :
Classe non générique analysée en utilisant les primitives du JDK 1.4
Entrez le nom d’une classe (ex : java.util.Date): java.util.Date
public class java.util.Date
implements java.io.Serializable,
java.lang.Cloneable,
java.lang.Comparable {
private
private
private
private
private
private
private
private
static final sun.util.calendar.BaseCalendar gcal;
static sun.util.calendar.BaseCalendar jcal;
transient long fastTime;
transient sun.util.calendar.BaseCalendar$Date cdate;
static int defaultCenturyStart;
static final long serialVersionUID;
static final [Ljava.lang.String; wtb;
static final [I ttb;
public
public
public
public
public
public
java.util.Date(int, int, int, int, int, int){}
java.util.Date(java.lang.String){}
java.util.Date(int, int, int, int, int){}
java.util.Date(int, int, int){}
java.util.Date(long){}
java.util.Date(){}
public
public
public
public
public
public
public
public
public
public
public
public
public
public
int hashCode(){}
int compareTo(java.util.Date){}
volatile int compareTo(java.lang.Object){}
java.lang.Object clone(){}
boolean equals(java.lang.Object){}
java.lang.String toString(){}
static long parse(java.lang.String){}
boolean after(java.util.Date){}
boolean before(java.util.Date){}
int getDate(){}
int getHours(){}
int getMinutes(){}
int getMonth(){}
int getSeconds(){}
Séance de TP n◦ 02– Réflexivité en Java
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
2
long getTime(){}
int getYear(){}
void setTime(long){}
static long UTC(int, int, int, int, int, int){}
int getDay(){}
int getTimezoneOffset(){}
void setDate(int){}
void setHours(int){}
void setMinutes(int){}
void setMonth(int){}
void setSeconds(int){}
void setYear(int){}
java.lang.String toGMTString(){}
java.lang.String toLocaleString(){}
final native java.lang.Class getClass(){}
final void wait() throws java.lang.InterruptedException{}
final void wait(long, int) throws java.lang.InterruptedException{}
final native void wait(long) throws java.lang.InterruptedException{}
final native void notify(){}
final native void notifyAll(){}
}
Classe générique analysée en utilisant les primitives de Java 5
public class java.util.HashMap <K, V>
extends java.util.AbstractMap <K, V>
implements java.util.Map <K, V>,
java.lang.Cloneable,
java.io.Serializable {
static final int DEFAULT_INITIAL_CAPACITY;
static final int MAXIMUM_CAPACITY;
static final float DEFAULT_LOAD_FACTOR;
transient [Ljava.util.HashMap$Entry; table;
transient int size;
int threshold;
final float loadFactor;
transient volatile int modCount;
static final java.lang.Object NULL_KEY;
private static final boolean useNewHash;
private transient java.util.Set <E> entrySet;
private static final long serialVersionUID;
public
public
public
public
java.util.HashMap
java.util.HashMap
java.util.HashMap
java.util.HashMap
public
public
public
public
public
public
public
public
public
public
public
public
public
java.lang.Object put(java.lang.Object, java.lang.Object){}
java.lang.Object clone(){}
void clear(){}
java.util.Set <E> entrySet(){}
java.lang.Object get(java.lang.Object){}
void putAll(java.util.Map <K, V>){}
int size(){}
java.util.Collection <E> values(){}
java.lang.Object remove(java.lang.Object){}
boolean containsKey(java.lang.Object){}
boolean containsValue(java.lang.Object){}
boolean isEmpty(){}
java.util.Set <E> keySet(){}
<K,
<K,
<K,
<K,
V>(){}
V>(java.util.Map <K, V>){}
V>(int, float){}
V>(int){}
Séance de TP n◦ 02– Réflexivité en Java
public
public
public
public
public
public
public
public
public
3
int hashCode(){}
boolean equals(java.lang.Object){}
java.lang.String toString(){}
final native java.lang.Class <T> getClass(){}
final void wait() throws java.lang.InterruptedException{}
final void wait(long, int) throws java.lang.InterruptedException{}
final native void wait(long) throws java.lang.InterruptedException{}
final native void notify(){}
final native void notifyAll(){}
}
Voici un squelette de la classe “AnalyseurDeClasse.java”.
2 /∗ ∗
3
4
5
6
7
∗ @version 1.00 23 Mars 2001
∗ @author Michel Buffa
∗ Inspiré par la classe Reflectiontest
. java de
∗ Cay S. Horstmann & Gary Cornell , publiée dans le livre
∗/
10
import java.lang.reflect.*;
import java.io.*;
12
public class AnalyseurDeClasse {
9
14
Core Java , Sun Press
public static void analyseClasse(String nomClasse) throws
ClassNotFoundException {
15
// Récupération
16
Class cl = getClasse(nomClasse);
18
afficheEnTeteClasse(cl);
20
System.out.println();
afficheAttributs(cl);
21
d’ un objet
de type Class correspondant
au nom passé en paramètres
System.out.println();
afficheConstructeurs(cl);
23
24
System.out.println();
afficheMethodes(cl);
26
27
29
// L’ accolade fermante
30
System.out.println("}");
de fin
de classe
!
31
}
34
/∗ ∗ Retourne la classe
35
public static Class getClasse(String nomClasse) throws
ClassNotFoundException {
// CODE A ECRIRE
36
37
dont le nom est passé en paramètre ∗/
}
39
/∗ ∗ Cette méthode affiche
40
public static void afficheEnTeteClasse(Class cl) {
41
42
44
45
// Affichage du modifier
// CODE A ECRIRE
// Récupération
par ex "public
class
Toto extends
Tata implements
Titi , Tutu {" ∗/
et du nom de la classe
de la superclasse
si elle
Class supercl = // CODE A ECRIRE
existe
( null si cl est le type Object )
Séance de TP n◦ 02– Réflexivité en Java
4
// On ecrit le "extends " que si la superclasse
// différente
de Object
// CODE A ECRIRE
47
48
49
// Affichage des interfaces
// CODE A ECRIRE
51
52
que la classe
54
// Enfin , l ’ accolade ouvrante
55
System.out.print(" {\n");
est non nulle
implemente
!
56
}
58
public static void afficheAttributs(Class cl) {
// CODE A ECRIRE
59
60
}
62
public static void afficheConstructeurs(Class cl) {
// CODE A ECRIRE
63
System.out.println("{}");
64
}
65
public static void afficheMethodes(Class cl) {
68
69
// CODE A ECRIRE
70
System.out.println("{}");
}
71
public static String litChaineAuClavier() throws IOException {
BufferedReader br = new BufferedReader(new
InputStreamReader(System.in));
return br.readLine();
}
73
74
75
76
public static void main(String[] args) {
boolean ok = false;
78
79
while(!ok) {
try {
System.out.print("Entrez le nom d’une classe (ex : java.util.Date):
");
String nomClasse = litChaineAuClavier();
81
82
83
84
analyseClasse(nomClasse);
86
ok = true;
} catch(ClassNotFoundException e) {
System.out.println("Classe non trouvée.");
}catch(IOException e) {
System.out.println("Erreur d’E/S!");
}
88
89
90
91
92
93
}
94
}
95
97
et
}
Vous devez compléter le code. N’oubliez de travailler de manière incrémentale (d’abord au moins le nom de la
classe, puis les classes ancêtres, etc).
Remarque: Pour commencer, ne vous occupez pas de la généricité : partout ou vous manipulerez un objet de type
"Class", vous l’afficherez simplement par son nom en utilisant la méthode getName.
Corrigé ⇒
Séance de TP n◦ 02– Réflexivité en Java
5
On obtient les classes suivantes.
Classe AnalyseurDeClasse.java
1 /∗ ∗
2
3
4
5
6
8
9
10
12
13
14
16
∗ @version 1.00 23 Mars 2001
∗ @author Michel Buffa
∗ Inspiré par la classe Reflectiontest
. java de
∗ Cay S. Horstmann & Gary Cornell , publiée dans le livre
∗/
Core Java , Sun Press
import java.lang.reflect.*;
import java.io.*;
import javax.swing.*;
public class AnalyseurDeClasse {
JPanel jPanel1 = new JPanel();
JButton jButton1 = new JButton();
public static void analyseClasse(String nomClasse) throws
ClassNotFoundException {
17
// Récupération
18
Class cl = Class.forName(nomClasse);
20
afficheEnTeteClasse(cl);
22
System.out.println();
afficheAttributs(cl);
23
d’ un objet
de type Class correspondant
au nom passé en paramètres
System.out.println();
afficheConstructeurs(cl);
25
26
System.out.println();
afficheMethodes(cl);
28
29
31
// L’ accolade fermante
32
System.out.println("}");
de fin
de classe
!
33
}
35
public static void afficheEnTeteClasse(Class cl) {
36
//
37
System.out.print(Modifier.toString(cl.getModifiers()));
System.out.print(" class " + cl.getName());
38
40
Affichage
// Récupération
du modifier , du nom de la classe
de la superclasse
si elle
existe
et son entête
si elle
( null si cl est le type Object )
41
Class supercl = cl.getSuperclass();
43
44
// On ecrit le "extends " que si la superclasse
// différente
de Object
45
if (supercl != null && !supercl.equals(Object.class))
46
47
48
est non nulle
// ou variante suivante :
//
if ( supercl != null && supercl . getSuperclass
() != null )
50
// Affichage
51
Class[] interfaces = cl.getInterfaces();
if (interfaces.length != 0) {
System.out.print(" implements ");
for(int i = 0; i < interfaces.length; i++) {
System.out.print(interfaces[i].getName());
if (i != (interfaces.length -1)) {
System.out.print(", ");
52
53
54
55
56
57
et
System.out.print(" extends " + supercl.getName());
des interfaces
que la classe
est générique
implemente
Séance de TP n◦ 02– Réflexivité en Java
6
}
58
}
59
}
60
61
// Enfin , l ’ accolade ouvrante
62
System.out.print(" {\n");
!
63
}
65
public static void afficheAttributs(Class cl) {
Field[] fields = cl.getDeclaredFields();
66
for (int i = 0; i < fields.length; i++){
68
69
// Le ième attribut
70
Field f = fields[i];
71
// Le type du ième attribut
72
Class type = f.getType();
73
// Son nom sous forme de chaîne de caractère
74
String name = f.getName();
76
// On écrit
77
System.out.print("\t" + Modifier.toString(f.getModifiers()));
d’ abord son modifier
78
// Puis son type et son nom !
79
System.out.println(" " + type.getName() + " " + name + ";");
}
80
81
}
83
public static void afficheConstructeurs(Class cl) {
Constructor[] constructors = cl.getDeclaredConstructors();
84
for (int i = 0; i < constructors.length; i++) {
86
87
// Le ième constructeur
88
Constructor c = constructors[i];
90
// Affichage
91
92
System.out.print("\t" + Modifier.toString(c.getModifiers()));
System.out.print(" " + cl.getName() + "(");
du modifier
+ du nom de la classe
( eq. nom du constructeur
94
// Affichage
du type des paramètres
96
// Le type des
97
102
Class[] paramTypes = c.getParameterTypes();
for (int j = 0; j < paramTypes.length; j++) {
if (j > 0) System.out.print(", ");
System.out.print(paramTypes[j].getName());
}
System.out.print(")");
104
// Affichage
105
Class[] exceptions = c.getExceptionTypes();
if (exceptions.length != 0) {
System.out.print(" throws ");
for(int k = 0; k < exceptions.length; k++) {
System.out.print(exceptions[k]);
if (k != (exceptions.length -1)) {
System.out.print(", ");
}
}
}
System.out.println("{}");
98
99
100
101
106
107
108
109
110
111
112
113
114
115
paramètres
est un tableau
d’ objet
Class
des Exceptions
}
117
118
}
120
public static void afficheMethodes(Class cl) {
Method[] methods = cl.getMethods();
121
)
Séance de TP n◦ 02– Réflexivité en Java
7
for (int i = 0; i < methods.length; i++) {
123
124
// La ième méthode
125
Method m = methods[i];
126
// Le type de retour
127
Class retType = m.getReturnType();
128
// Le tableau
129
Class[] paramTypes = m.getParameterTypes();
des types des paramètres
130
// Le nom de la méthode
131
String name = m.getName();
133
// Affichage
134
135
System.out.print("\t" + Modifier.toString(m.getModifiers()));
System.out.print(" " + retType.getName() + " " + name);
137
// Affichage
138
143
System.out.print("(");
for (int j = 0; j < paramTypes.length; j++) {
if (j > 0) System.out.print(", ");
System.out.print(paramTypes[j].getName());
}
System.out.print(")");
145
// Affichage
146
Class[] exceptions = m.getExceptionTypes();
if (exceptions.length != 0) {
System.out.print(" throws ");
for(int k = 0; k < exceptions.length; k++) {
System.out.print(exceptions[k].getName());
if (k != (exceptions.length -1)) {
System.out.print(", ");
}
}
}
System.out.println("{}");
139
140
141
142
147
148
149
150
151
152
153
154
155
156
du modifier
+ type de retour
+ nom de la méthode
des types des paramètres
des Exceptions
}
157
158
}
160
public static String litChaineAuClavier() throws IOException {
BufferedReader br = new BufferedReader(new
InputStreamReader(System.in));
return br.readLine();
}
161
162
163
165
166
public static void main(String[] args) {
boolean ok = false;
while(!ok) {
try {
System.out.print("Entrez le nom d’une classe (ex : java.util.Date):
");
String nomClasse = litChaineAuClavier();
168
169
170
171
analyseClasse(nomClasse);
173
ok = true;
} catch(ClassNotFoundException e) {
System.out.println("Classe non trouvée.");
}catch(IOException e) {
System.out.println("Erreur d’E/S!");
}
175
176
177
178
179
180
}
181
182
}
Séance de TP n◦ 02– Réflexivité en Java
public AnalyseurDeClasse() {
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
private void jbInit() throws Exception {
jButton1.setText("jButton1");
jPanel1.add(jButton1, null);
}
184
185
186
187
188
189
190
191
192
193
194
195
196
8
}
Classe Methodes
2 /∗ ∗
3
4
5
7
8
∗ Trouver toutes les méthodes d’ une classe ,
∗ y compris celles qui sont héritées .
∗/
import java.lang.reflect.*;
import java.util.*;
10 /∗ ∗
11
12
13
14
15
16
17
18
19
∗ Affiche les méthodes d’ une classe .
∗ @param class la classe dont on veut les méthodes .
∗ @param visionPaquetage vrai si on veut retenir les méthodes "package "
∗ des classes ancêtre qui sont dans le même paquetage que class .
∗ C’est −à−dire, on veut les méthodes de class visible du même
∗ paquetage .
∗/
public class Methodes {
public static void printMethods(Class cl, boolean visionPaquetage) {
20
// Vrai si on affiche
21
boolean retenirPaquetage = false;
les méthodes d’ accès "package "
22
// Paquetage de la classe
23
Package paquetage = cl.getPackage();
25
/∗ Si on examine une classe
classes private . ∗/
26
27
28
( pour le comparer à celui
ancêtre , on ne retient
des classes
mères )
pas les
boolean ancetre = false; // vrai si on examine une classe ancêtre
HashSet methodes = new HashSet();
29
// On remonte les classes
30
while (cl != null) {
System.out.println("Classe " + cl.getName() + "------------");
31
ancêtres
jusqu ’ à Object .
// Les méthodes qui sont déclarées
// ( pas héritées ) .
34
Method[] methods = cl.getDeclaredMethods();
35
// Est −ce que la classe est dans le même paquetage
// que la classe de départ ?
36
dans la classe
elle −même
33
32
37
retenirPaquetage = (paquetage == cl.getPackage()) &&
visionPaquetage;
39
for (int i = 0; i < methods.length; i++) {
Method m = methods[i];
int modifieurs = m.getModifiers();
40
41
Séance de TP n◦ 02– Réflexivité en Java
// Cas où on ne doit pas retenir la méthode :
// elle est private , ou "package " et on ne retient
// pas les méthodes "package ".
42
43
44
if (ancetre
&& (Modifier.isPrivate(modifieurs)
|| ((!Modifier.isPublic(modifieurs))
&& (!Modifier.isProtected(modifieurs))
&& !retenirPaquetage))) {
continue;
}
45
46
47
48
49
50
51
Class[] paramTypes = m.getParameterTypes();
String nomMethode = m.getName();
53
54
55
// System . out . println (" Nom de la méthode : " + nomMethode);
56
Class retType = m.getReturnType();
String nomTypeRetour;
if (retType == null) {
nomTypeRetour = "void";
}
else {
nomTypeRetour = retType.getName();
}
Methode methode =
new Methode(modifieurs, nomMethode, paramTypes, nomTypeRetour,
cl.getName());
if (! methodes.add(methode)) {
57
58
59
60
61
62
63
64
65
66
67
// System . out . println (" Déjà dans le set : " + methode ) ;
68
continue;
69
}
70
71
// On garde la méthode
72
System.out.println(methode);
}
cl = cl.getSuperclass();
ancetre = true;
73
74
75
}
76
// System . out . println ( methodes ) ;
77
78
}
80
// Juste
81
private int[][] machin(Boolean[] truc) {
return null;
}
82
83
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
pour tester
les noms de tableaux
/∗ ∗
∗ Un profil de méthode .
∗
∗ Sert pour savoir si une méthode d’ une classe ancêtre
∗ doit être affichée ou non.
∗ L’ idée est de ranger les méthodes dans un Set en s ’ arrangeant
∗ pour que les méthodes de même signature soient égales .
∗ D’après les propriétés
des Set , un objet n’ est pas rangé
∗ dans un Set si celui −ci contient déjà un objet égal au sens de equals .
∗ Attention ! ne pas oublier de redéfinir
la méthode hashcode dans la
∗ classe Methode, et elle doit être compatible avec equals .
∗ Si on commence par les méthodes de la classe pour remonter
∗ dans les classes mères jusqu ’ à Object , on ne rangera donc pas
∗ les méthodes qui ont été redéfinies
dans une des classes
∗ filles
( car elles auront même signature qu’ une méthode déjà
∗ rencontrée ) .
∗
∗/
private static class Methode {
private int modifieurs;
private String nom;
9
Séance de TP n◦ 02– Réflexivité en Java
10
private String paramTypes;
private String returnType;
private String classeDefinition;
106
107
108
/∗ ∗
∗ @param modifieurs modificateurs
de la méthode .
∗ @param nom nom de la méthode .
∗ @param paramTypes types des paramètres de la méthode .
∗ @param returnType type retour de la méthode .
∗ @param classeDefinition
classe dans laquelle cette méthode
∗
a été définie .
∗/
110
111
112
113
114
115
116
117
132
private Methode(int modifieurs, String nom, Class[] paramTypes,
String returnType, String classeDefinition ) {
this .modifieurs = modifieurs;
this .nom = nom;
this .paramTypes = "";
if (paramTypes.length > 0) {
for (int i = 0; i < paramTypes.length - 1; i++) {
this .paramTypes += transform(paramTypes[i].getName()) + ", ";
}
this .paramTypes +=
transform(paramTypes[paramTypes.length - 1].getName());
}
this .returnType = returnType;
this .classeDefinition = classeDefinition;
}
134
public boolean equals(Object objet) {
118
119
120
121
122
123
124
125
126
127
128
129
130
131
135
// Tester
136
Methode m = (Methode)objet;
return modifieurs == m.modifieurs && nom.equals(m.nom)
&& paramTypes.equals(m.paramTypes);
137
138
le cas où les modificateurs
sont dans un ordre différent
}
139
pour que ça marche avec HashSet ∗/
141
/∗ Indispensable
142
public int hashCode()
int result = 17;
result = result *
result = result *
return result * 37
}
143
144
145
146
147
//
//
//
//
//
149
150
151
152
153
{
37 + modifieurs;
37 + nom.hashCode();
+ paramTypes.hashCode();
Il reste à transformer les tableaux :
[ Ljava . lang . Object ; en java . lang . Object []
par exemple ,
[ I pour int [], [ B pour boolean [], etc ...
et aussi les tableaux à plusieurs dimensions
: [[ I en int [][]
public String toString() {
return classeDefinition + ": "
+ Modifier.toString(modifieurs) + " " + transform(returnType) + " "
+ nom + "(" + paramTypes + ")";
}
154
155
156
157
158
159
}
161
private static String transform(String nomClasseCode) {
if (!nomClasseCode.startsWith("[")) {
return nomClasseCode;
}
162
163
164
165
// C’est un tableau
166
int dimension = nomClasseCode.lastIndexOf("[") + 1;
168
String nomFinal;
if (nomClasseCode.endsWith(";")) {
169
(??)
Séance de TP n◦ 02– Réflexivité en Java
170
// C’est un tableau
171
nomFinal =
nomClasseCode.substring(dimension + 1, nomClasseCode.length() 1);
172
11
de type non primitif
}
else {
173
174
175
// C’est un tableau
176
char typePrimitif = nomClasseCode.charAt(dimension);
switch(typePrimitif) {
case ’B’:
nomFinal = "byte";
break;
case ’C’:
nomFinal = "char";
break;
case ’D’:
nomFinal = "double";
break;
case ’F’:
nomFinal = "float";
break;
case ’I’:
nomFinal = "int";
break;
case ’J’:
nomFinal = "long";
break;
case ’S’:
nomFinal = "short";
break;
case ’Z’:
nomFinal = "boolean";
break;
case ’V’:
nomFinal = "void";
break;
default :
nomFinal = "**type primitif inconnu**";
}
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
de type primitif
}
for (int i = 0; i < dimension; i++) {
nomFinal += "[]";
}
return nomFinal;
208
209
210
211
212
213
}
215
public static void main(String[] args) {
String nomClasse = null;
for (int i=0; i<args.length; i++) {
try {
nomClasse = args[i];
Class cl = Class.forName(nomClasse);
System.out.println("Méthodes de la classe " + nomClasse);
System.out.println("====================================================");
printMethods(cl, true);
System.out.println();
}
catch(ClassNotFoundException e) {
System.out.println("Classe " + nomClasse + " pas trouvée.");
}
}
}
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
}
Séance de TP n◦ 02– Réflexivité en Java
12
Exercice 2 : une méthode toString générique pour les bébêtes
Ecrivez, dans la classe BebeteAbstraite du précédent projet, une méthode :
public String toString() {...}
...qui affiche le nom des attributs et leur valeur, mais sans en connaître le nombre ni le type à l’avance.
N’essayez pas de voir les attributs hérités dans un premier temps. En effet, la méthode getDeclaredFields()
de la classe Class ne retourne que les attributs locaux.
Pour tester la méthode, faites par exemple afficher régulièrement les caractéristiques d’une bébête du simulateur
sur la sortie standard (prenez par exemple la première bébête dans le moteur de simulation du ChampDeBebetes).
Corrigé ⇒
On obtient les classes suivantes.
Classe BebeteAbstraite
81 //
83
84
85
86
87
88
89
90
91
92
93
94
95
96
98
99
100
101
102
103
104
105
106
107
108
109
111
112
ajouts
pour TD2 : réflexivité
public String toString(){
Class cl = getClass();
String r = cl.getName() + FieldsFromClass(cl) +"\n";
Class[] allsc = allSuperClasses(cl); // cf plus loin
for (int ci = 0; ci < allsc.length; ci++) {
Class sc = allsc[ci];
r += allsc[ci].getName()+FieldsFromClass(allsc[ci])+"\n";;
if (ci < allsc.length - 1)
r += ",";
else
r += "]";
}
return r;
}
// La reflexivité
de Java ne donne pas la liste de toutes les superclasses
:
// Il faut parcours le chemin dhéritage entre la classe en remontant jusqu ’ à la
// racine Object
private static Class[] allSuperClasses(Class cl) {
ArrayList rl = new ArrayList();
Class superC = cl.getSuperclass();
while (superC != null) {
rl.add(superC);
superC = superC.getSuperclass();
}
return (Class [])(rl.toArray(new Class[0]));
}
private String FieldsFromClass(Class c) {
String r = "[\n";
113
// On ne prend que les champs locaux à la classe , quelque soit
114
Field[] fields = c.getDeclaredFields();
for (int i = 0; i < fields.length; i++){
Field f = fields[i];
r += "\t" + f.getName() + "=";
try {
r += f.get(this);
} catch (IllegalAccessException e){
r += "???";
}
115
116
117
118
119
120
121
122
son modifieur
Séance de TP n◦ 02– Réflexivité en Java
if (i < fields.length - 1)
r += "\n";
else
r += "]";
123
124
125
126
}
System.out.println(r);
return r;
127
128
129
}
130
132
}
Classe ChampDeBebetes
1 /∗ ∗
2
3
4
5
6
∗ ChampDeBebtes : version pour des bebetes Emergentes avec toString Introspectif
∗ dans BebeteAbstraite
: un click sur l ’ écran affiche la bebete à proximité ,
∗ s ’ il y en a une.
∗ @author collet ( d’ après L. O’Brien , C. Reynolds & B. Eckel )
∗/
11
package tp1.bebetes;
import java.awt.*;
import java.util.*;
import java.awt.event.MouseEvent; /∗ Nouveau TD2 ∗/
13
public class ChampDeBebetes extends Panel implements Runnable {
8
9
10
15
16
17
18
20
21
22
24
25
26
27
28
private ArrayList lesBebetes;
static int largeur = 0;
static int hauteur = 0;
static int nombreDeBebetes = 250;
Thread leThread;
Frame toStringFrame = null; /∗ Nouveau TD2 Afficheur ∗/
TextArea ta;
/∗ Nouveau TD2 ∗/
public ChampDeBebetes(int largeur, int hauteur) {
this .largeur = largeur;
this .hauteur = hauteur;
setSize(largeur, hauteur);
lesBebetes = fabriqueBebetes(nombreDeBebetes);
/∗ Ajout TD2 ∗/
29
35
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
36
/∗ Fin Ajout TD2 ∗/
37
leThread = new Thread(this);
leThread.start();
30
31
32
33
34
38
39
}
40 /∗ ...
∗/
13
Séance de TP n◦ 02– Réflexivité en Java
131 /∗ ...
14
Ajout TD2 ∗/
private void jbInit() throws Exception {
this .addMouseListener(new java.awt.event.MouseAdapter() {
public void mousePressed(MouseEvent e) {
this_mousePressed(e);
}
});
133
134
135
136
137
138
139
}
141
void this_mousePressed(MouseEvent e) {
if (toStringFrame == null) {
142
// création
143
de la petite
fenêtre
d’ affichage
toStringFrame = new Frame("toString");
toStringFrame.setLocation(getX()+getWidth(),getY());
ta = new TextArea("...",20,60,TextArea.SCROLLBARS_NONE);
ta.setEnabled(false);
toStringFrame.add(ta,BorderLayout.CENTER);
toStringFrame.pack();
toStringFrame.show();
}
int mx = e.getX();
int my = e.getY();
144
145
146
147
148
149
150
151
152
153
154
// Recherche de la bebete la plus proche de la position
155
ListIterator l = lesBebetes.listIterator();
if (lesBebetes.size() > 0) {
BebeteAbstraite plusProche = (BebeteAbstraite)l.next();
float dmin = plusProche.distanceDepuisUnPoint(mx,my);
while(l.hasNext()) {
BebeteAbstraite b = (BebeteAbstraite)l.next();
float dminDeB = b.distanceDepuisUnPoint(mx,my);
if (dminDeB < dmin) {
dmin = dminDeB;
plusProche = b;
}
}
if (dmin > 30f)
ta.setText("Pas de bébête à proximité");
else
ta.setText(plusProche.toString());
}
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
}
172
/∗ Fin Ajout TD2 ∗/
173
174
de la souris
}
Exercice 3 : un tableau grossissant
Travail à effectuer
Récupèrez le fichier “ArrayGrowTest.java”, tiré du livre Core Java ("au coeur de Java" dans la version française).
1 /∗
2
3
4
∗ Cay S. Horstmann & Gary Cornell , Core Java
∗ Published By Sun Microsystems Press / Prentice −Hall
∗ Copyright ( C) 1997 Sun Microsystems Inc .
Séance de TP n◦ 02– Réflexivité en Java
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
∗ All Rights Reserved .
∗
∗ Permission to use , copy , modify , and distribute
this
∗ software and its documentation for NON−COMMERCIAL purposes
∗ and without fee is hereby granted provided that this
∗ copyright notice appears in all copies .
∗
∗ THE AUTHORS AND PUBLISHER MAKE NO REPRESENTATIONS OR
∗ WARRANTIES ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER
∗ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
∗ IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
∗ PARTICULAR PURPOSE, OR NON−INFRINGEMENT. THE AUTHORS
∗ AND PUBLISHER SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED
∗ BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
∗ THIS SOFTWARE OR ITS DERIVATIVES.
∗/
22 /∗ ∗
23
24
25
26
∗ @version 1.00 11 Mar 1997
∗ @author Cay Horstmann
∗ petites modifs pour le TP...
∗/
28
import java.lang.reflect.*;
30
public class ArrayGrowTest
{ public static void main(String[] args)
{ int [] a = { 1, 2, 3 };
Personne[] b = { new Personne("Maurice Chombier"), new
Personne("François Pignon") };
31
32
33
// a = ( int []) goodArrayGrow( a) ;
// arrayPrint ( a) ;
34
35
b = (Personne[])goodArrayGrow(b);
arrayPrint(b);
36
37
System.out.println
("The following call will generate an exception.");
b = (Personne[])badArrayGrow(b);
39
40
41
42
}
44
static Object[] badArrayGrow(Object[] a)
{ int newLength = a.length * 11 / 10 + 10;
Object[] newArray = new Object[newLength];
System.arraycopy(a, 0, newArray, 0, a.length);
return newArray;
}
45
46
47
48
49
static
{
51
52
Object[] goodArrayGrow(Object []a)
// CODE A ECRIRE !
53
54
}
56
static void arrayPrint(Object a)
{ Class cl = a.getClass();
if (!cl.isArray()) return;
Class componentType = a.getClass().getComponentType();
int length = Array.getLength(a);
System.out.println(componentType.getName()
+ "[" + length + "]");
for (int i = 0; i < Array.getLength(a); i++)
System.out.println(Array.get(a, i));
}
57
58
59
60
61
62
63
64
65
66
}
15
Séance de TP n◦ 02– Réflexivité en Java
68
69
class Personne {
private String nom;
public Personne(String nom) {
this .nom = nom;
}
71
72
73
public String toString() {
return nom;
}
75
76
77
78
16
}
Complétez la méthode goodArrayGrow(...) pour qu’elle fonctionne. Dans un premier temps laissez les deux lignes
:
//a = (int[])goodArrayGrow(a);
//arrayPrint(a);
...en commentaires.
Ce que vous devez obtenir c’est :
javaw ArrayGrowTest
Personne[12]
Maurice Chombier
François Pignon
null
null
...
The following call will generate an exception.
java.lang.ClassCastException: [Ljava.lang.Object;
at ArrayGrowTest.main(ArrayGrowTest.java:40)
Exception in thread "main"
Process ArrayGrowTest exited abnormally with code 1
Tous les "null" qui s’affichent sont normaux, ils prouvent que votre tableau a grossi.
Décommentez maintenant les deux lignes correspondant au tableau de int. Ca devrait ne plus marcher... Essayez
de faire quand même marcher le programme (aide: utilisez la classe Array) !
Corrigé ⇒
On obtient la classe suivante.
Classe ArrayGrowTest
52
53
54
55
static
Object goodArrayGrow(Object []a)
// Attention ! Object [] n’ est pas du type Object
// Pour faire le cast b = ( Personne []) badArrayGrow( b)
// il vaut mieux que le type retourné soit de type Object
56
{ Class cl = a.getClass();
57
// On vérifie
que l ’ objet a est bien de type Array pour lui appliquer
// la méthode getComponentType ()
58
59
if (!cl.isArray()) return null;
60
// Récupération
61
Class componentType = a.getClass().getComponentType();
du type des éléments
et de la longueur
Séance de TP n◦ 02– Réflexivité en Java
17
62
int length = Array.getLength(a);
63
// calcule
64
int newLength = length * 11 / 10 + 10;
66
// construction
67
Object newArray = Array.newInstance(componentType, newLength);
de la nouvelle
longueur
du nouveau tableau
68
// recopie
69
System.arraycopy(a, 0, newArray, 0, length);
return newArray;
70
71
des anciennes
valeurs
}
1. Pour ceux qui s’ennuient...
• Terminez l’analyseur de classes pour qu’ils affichent correctement toutes les informations de généricité de la
classe analysée.
• Reprenez l’exercice 2, écrivez un écouteur du clic souris sur le champ de Bebetes, repérez la bébête la plus
proche et affichez ses caractéristiques avec toString dans une fenêtre spécifique.