Universit Cadi Ayyad - Marrakech
cole Suprieure de Technologie d'Essaouira
Enseignant: A. Darouichi
Anne 2015-2016
DUT Gnie Informatique
Semestre 3
TP: POO en Java: Clonage d'objets
Srie 7
Exercice 1
1 Le Clonage
Le clonage en gnral est la cration d'un nouvel objet (une instance d'une
classe) partir d'une instance dj existante. En java le clonage sert faire
la copie d'un objet dans un autre. En eet, si on se contente d'crire a = b ;
on obtient la copie des rfrences (b sur a), et non la duplication de l'objet b
dans a.
Pour qu'un objet soit clonable (copiable), sa classe doit implmenter la mthode clone() de l'interface Cloneable. En fait, la mthode clone() est
dnie pour la classe Object et s'applique donc tous les objets Java.
En pratique, les sous-classes qui le dsirent doivent implmenter l'interface
Cloneable et rednir la mthode clone(). Cette rednition peut se limiter
faire appel super.clone() ; i.e. la mthode mre hrite. Celle-ci peut
gnrer l'exception CloneNotSupportedException.
2 Simple Clonage
2.1
Exemple
Dans cet exemple, on va crer un objet Cellule suivi de son clonage. Soit
la classe Cellule, constitue d'un entier et d'un tableau :
class Cellule extends Object implements Cloneable {
// Doit implmenter la mthode clone() de l'interface Cloneable.
// Mthode qui fait le clonage.
// Donnes
int i = 0;
int[] t = {1, 2};
// Mthodes
public Object clone(){
try {
return super.clone();
}
catch (CloneNotSupportedException e){
throw new InternalError();
}
}
public void afficher(){
System.out.println(i +" "+ t[0]+" "+t[1]);
}
}
Tester cette classe avec :
class TestClone {
public static void main(String args[]){
Cellule x = new Cellule(); // x Objet Cellule
x.afficher();
Cellule y = (Cellule) x.clone(); // y clone de x
y.afficher();
}
}
et constater le rsultat :
i=0 t=(1, 2) // valeurs de la cellule x
i=0 t=(1, 2) // valeurs de la cellule y
Remarquer qu'on aurait pu faire une aectation d'objets dans main(). Au
lieu de faire
Cellule y = (Cellule) x.clone(); // initialisation par clonage
On fait
Cellule y = new Cellule();
y = (Cellule) x.clone(); // vraie affectation d'un clone
Exercice 2
1. Invoquer la mthode toString() sur les deux objets x et y .
2. Que remarquez-vous ?
2
3 Clonage superciel/Copie Supercielle/Shallow
Copy
En ralit, le clonage est superciel. L'entier x.i a t copi dans y.i,
mais pour le tableau t, c'est la rfrence qui est copie (non les lments
du tableau.) Pour le constater, rajouter la classe Cellule une mthode qui
change les lments d'un cellule.
3.1
Exemple
Rajouter la classe Cellule la mthode
public void changeMe(){
i = 10;
t[0] = 11;
t[1] = 12;
}
et vrier qu'en rajoutant dans main() les instructions :
x.changeMe();
x.afficher();
y.afficher();
on obtient :
i=10 t=(11, 12) // x change
i=0 t=(11, 12) // y aussi pour la partie tableau (mme objet r\'ef\'erence)
4 Clonage en profondeur/Deep Copy
Pour copier toute un objet Cellule, y compris le tableau, il faut cloner ce
dernier (le copier aussi).
4.1
Exemple
Pour Cloner aussi le tableau. On change la mthode clone() de la classe
Cellule, pour cloner le tableau (le copier aussi).
public Object clone(){
try {
Cellule tmp = (Cellule) super.clone();
tmp.t = (int []) this.t.clone(); //clonage de this.t
return tmp;
}
catch (CloneNotSupportedException e){
throw new InternalError();
}
}
On cre par clonage une cellule temporaire tmp et on modie son tableau
tmp.t par recopie ( this > t.clone() ).
Exercice 3
vrier le.
4.2
Exemple
Variation sur le mme thme
Cette fois-ci, on va copier un un les lments d'un objet Cellule sans faire
appel super.clone(). On modie la mthode clone() de la classe Cellule
comme suit.
public Object clone(){ // sans clone super.clone()
Cellule tmp = new Cellule();
tmp.i=i;
tmp.t = (int []) this.t.clone(); //clonage de this.t
return tmp;
}
4.3
Exemple
Constructeur Cellule par copie
On peut crer un constructeur par copie pour la classe Cellule.
public Cellule (Cellule x){
this.i = x.i;
for (int i=0; i<2; i++)
this.t[i]=x.t[i];
}
et qu'on peut utiliser par
Cellule x = new Cellule();
...
Cellule y = new Cellule(x); // initialisation par copie
Exercice 4
1. Le vrier.
2. Quelle est la dirence par rapport la mthode clone() ?
Exercice 5
1. Crer les chiers Java suivant
EntierA.java
public class EntierA implements Cloneable {
private int entier = 10;
public int getEntier() {
return entier;
}
public void setEntier(int entier) {
this.entier = entier;
}
@Override
public EntierA clone() throws CloneNotSupportedException {
return (EntierA)super.clone();
}
}
EntierB.java
public class EntierB {
private int entier = 1000;
public int getEntier() {
return entier;
}
public void setEntier(int entier) {
this.entier = entier;
}
}
EssaiClone.java
class EssaiClone {
public static void main(String arg[]) throws CloneNotSupportedException {
ObjetClonable I = new ObjetClonable(), J;
J = I.clone();
System.out.println("Dans l'original " + I.getEntierLocal() + " " +
I.getEntierA().getEntier() + " " +
I.getTableau()[1] + " " +
I.getEntierB().getEntier());
System.out.println("Dans la copie " + J.getEntierLocal() + " " +
J.getEntierA().getEntier() + " "
+ J.getTableau()[1] + " " +
J.getEntierB().getEntier());
I.setEntierLocal(2);
I.getEntierA().setEntier(20);
I.getTableau()[1] = 200;
I.getEntierB().setEntier(3000);
System.out.println("Apres changement de tout ce que contient l'original :");
System.out.println("Dans l'original " + I.getEntierLocal() + " " +
I.getEntierA().getEntier() + " " +
I.getTableau()[1] + " " +
I.getEntierB().getEntier());
System.out.println("Dans la copie " +
J.getEntierLocal() + " " +
J.getEntierA().getEntier() + " " +
J.getTableau()[1] + " " +
J.getEntierB().getEntier());
}
}
ObjetClonable.java
public class ObjetClonable implements Cloneable {
private int entierLocal = 1;
private EntierA entierA = new EntierA();
private int[] tableau = {0, 100};
private EntierB entierB = new EntierB();
@Override
public ObjetClonable clone() throws CloneNotSupportedException {
ObjetClonable copie = (ObjetClonable)super.clone();
copie.entierA = entierA.clone();
copie.tableau = new int[tableau.length];
System.arraycopy(tableau, 0, copie.tableau, 0 , tableau.length);
return copie;
}
public int getEntierLocal() {
return entierLocal;
}
public void setEntierLocal(int entier) {
this.entierLocal = entier;
}
public int[] getTableau() {
return tableau;
}
public EntierA getEntierA() {
return entierA;
}
public EntierB getEntierB() {
return entierB;
}
}
2. Excuter ces programmes Java ?
3. Que remarquez-vous ?