IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

avec Java Discussion :

Réaliser une copie


Sujet :

avec Java

  1. #1
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 754
    Points : 376
    Points
    376
    Par défaut Réaliser une copie
    Bonsoir, je vous explique mon problème aussi simplement que possible.


    Admettons une classe de cette forme

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public class Test{
     public int nb;
     
    public Test(int n) {
      this.nb=n;
    }
     
    }
    Si je crée deux instances

    Test t1=new Test(5);
    Test t2=t1;
    t2++;

    Un problème survient t1 et t2 valent 6
    Alors que normalement je ne voudrais que seulement t2 soit modifié


    Qu'à cela ne tienne, j'ai trouvé la parade

    je n'ai qu'à réaliser un second constructeur

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public Test(Test t){
     this.nb=t.nb;
    }

    A ce moment là, j'aurais bien un résultat égal à 5 et l'autre à 6.




    ==> Oui mais !

    Si on a un type qui n'est pas primitif cette solution ne marche plus

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public class Test{
     public typeA a;
     
    public Test(typeA b) {
      this.a=b;
    }
     
    }
    A ce moment là, redéfinir le constructeur ne marche plus.


    J'en suis arrivée à la conclusion qu'il me fallait implémenter l'interface et redéfinir clone.

    Donc, dans ma classe typeA, j'ai fais la méthode clone

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public Object clone() {
    		Object o = null;
    		try {
    			// On récupère l'instance à renvoyer par l'appel de la 
    			// méthode super.clone()
    			o = super.clone();
    		} catch(CloneNotSupportedException cnse) {
    			// Ne devrait jamais arriver car nous implémentons 
    			// l'interface Cloneable
    			cnse.printStackTrace(System.err);
    		}
    		// on renvoie le clone
    		return o;
    	}

    Mais, même avec ça, mes deux instances de classes restent lié...donc je ne sais plus vraiment quoi faire...


    Comment puis je "sauvegarder" l'état d'un objet en travaillant sur des copies.

    C'est assez gênant car je fais intervenir de l'aléatoire et comme ça prend le même objet en référence, je finis avec la même série aléatoire à chaque fois...

  2. #2
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,



    Tout d'abord une petite remarque concernant ton traitement de l'exception CloneNotSupportedException.
    Ok elle ne devrait jamais arrivée et c'est déjà bien de l'afficher... mais en fait c'est pas top.

    En effet si par malheur l'exception survient (par exemple si le "implements Cloneable" est supprimé par erreur), ta méthode clone() va se contenter d'afficher une trace sur la console et elle va retourner null et générer un NullPointerException.
    Pour peu que ton application soit un peu complexe et que tu n'utilises pas l'objet cloné immédiatement, tu risque de perdre un temps fou à retrouver l'origine exact du problème.
    Le NPE pourrait te remonter par un système de bug-report, tandis que le CloneNotSupportedException serait perdu au milieu des logs que personne ne lit !!!

    En clair au lieu d'avoir :
    • CloneNotSupportedException dans la méthode clone() de la classe Test.


    Tu risque d'avoir une erreur bien moins compréhensible :
    • NullPointerException dans la méthode jeFaisQuelqueChose() de la classe UneTouteAutreClasse.



    Pire : ton programme pourrait continuer à tourner s'il gère les null... mais en faisant tout autre chose de ce que tu t'attends !



    Il vaut mieux remonter l'exception immédiatement, quitte à l'englober dans une RuntimeException pour ne plus avoir à la traiter :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    		} catch (CloneNotSupportedException cnse) {
    			throw new RuntimeException(cnse);
    		}
    Au moins là en cas de soucis tu auras une exception qui fera planter ton programme immédiatement... ce qui permettra de le corriger plus rapidement




    Au passage depuis Java 5.0 on peut redéfinir le type de retour de la méthode pour le spécialiser et ne pas avoir à s'embêter à recaster partout.
    Bref la base de la méthode ressemblerait à cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    class Test {
     
    	public Test clone() {
    		try {
    			// On récupère l'instance à renvoyer par l'appel de la
    			// méthode super.clone()
    			return (Test) super.clone();
    		} catch (CloneNotSupportedException cnse) {
    			// Ne devrait jamais arriver car nous implémentons
    			// l'interface Cloneable
    			throw new RuntimeException(cnse);
    		}
    	}
     
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Test t1 = new Test();
    // plus de cast !
    Test t2 = t1.clone();




    Enfin pour revenir sur ton problème : le clone() n'est pas récursif.
    Il va simplement te créer un nouvel objet du même type, auquel il affectera les mêmes valeurs.
    Du coup pour les primitifs on a bien une valeur distincte en mémoire... mais pour les objets on a une référence distincte, mais qui pointe vers le même objet !
    Donc en fait il va falloir cloner manuellement tous les attributs de ta classe qui ne sont pas immuable :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    class Test implements Cloneable {
     
    	private int nb;
    	private String str;
    	private TypeA a;
     
    	public Test clone() {
    		try {
    			// On récupère l'instance à renvoyer par l'appel de la
    			// méthode super.clone()
    			Test cloned = (Test) super.clone();
     
    			// Et on clone manuellement tous les types mutables :
    			cloned.a = cloned.a.clone();
     
    			// Le type 'String' est immuable, donc pas besoin de le cloner
     
    			return cloned;
    		} catch (CloneNotSupportedException cnse) {
    			// Ne devrait jamais arriver car nous implémentons
    			// l'interface Cloneable
    			throw new RuntimeException(cnse);
    		}
    	}
     
    }


    a++

  3. #3
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2011
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 754
    Points : 376
    Points
    376
    Par défaut
    Ah super merci ! Si ça marche vraiment comme ça tu me sauves la vie


    Juste une dernière question, si l'un de mes attribut n'est pas un type primitif et qu'il se présente sous la forme de tableau ou de liste

    Du genre

    TypeA[] a
    ArrayList<TypeB> b


    On va devoir cloner chaque élément un par un ou il y aura une astuce pour directement cloner le tableau/liste ? Disons que je ne me vois pas vraiment écrire a.clone() dans cette situation là...

Discussions similaires

  1. Réponses: 7
    Dernier message: 13/02/2006, 18h55
  2. [FLASH MX] Comment réaliser une forme dentelée
    Par celina5880 dans le forum Flash
    Réponses: 4
    Dernier message: 04/11/2004, 17h48
  3. [TQuery]Réaliser une requete à partir d'une requete
    Par Eric SAULNIER dans le forum Bases de données
    Réponses: 2
    Dernier message: 09/07/2004, 12h00
  4. Copier et afficher une copie d'ecran
    Par Bobx dans le forum Langage
    Réponses: 6
    Dernier message: 02/08/2002, 22h20
  5. Peux t'on créer une copie locale de l'objet partagé?
    Par Anonymous dans le forum CORBA
    Réponses: 8
    Dernier message: 16/04/2002, 16h20

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo