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

Langage Java Discussion :

[String]passage de String par reference?


Sujet :

Langage Java

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2003
    Messages
    35
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 35
    Points : 25
    Points
    25
    Par défaut [String]passage de String par reference?
    Bonjour,

    J'ai un problème relatif à la mise à jour d'un objet String instancié dans une méthode A(), et modifié dans une méthode B() (qui est appellé à partir de A). Les deux méthodes faisant partie de la meme classe.

    En effet en revenant dans A() apres l'appel a B(), la string n'est pas mise a jour.

    Exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public declaration() {
       String test= new String();
       affectation (test);
       System.out.println("affichage valeur chaine = " + test);
    }
     
    public static void affectation (String chaine){
       chaine = "test";
    }
    Au final, dans la console on ne voit que
    affichage valeur chaine =

    Si j'ai de bons souvenirs, les objets java sont passés par référence. Donc en faisant comme ca, je devrais pouvoir donner une valeur à ma chaine.

    [ Modéré par Bulbo ]
    Ajout des balises code
    Les Règles du Forum

  2. #2
    Membre expert Avatar de KiLVaiDeN
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 851
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 851
    Points : 3 480
    Points
    3 480
    Par défaut
    Salut,

    Je ne voudrais pas dire de bêtise, mais le fait de faire une affectation à un objet String équivaut à faire un new.

    Donc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    String monString = "couleurBleu";
    est equivalent à

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    String sonString = new String("à Paillette");
    Donc du coup, ta méthode A() a une référence sur un objet String, cet objet est persistant en mémoire, et dans ta méthode B() tu crées un deuxième objet, uniquement visible dans la méthode B().

    Pour bien faire dans ces cas là, il faut faire une méthode qui retourne le String modifié, ou bien mieux, utiliser les StringBuffer qui sont fait pour ça.
    K

  3. #3
    Membre actif Avatar de xxaragornxx
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    241
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 241
    Points : 253
    Points
    253
    Par défaut
    Citation Envoyé par KiLVaiDeN
    Je ne voudrais pas dire de bêtise, mais le fait de faire une affectation à un objet String équivaut à faire un new.
    .
    C'est tout à fait ça !

  4. #4
    Rédacteur
    Avatar de bulbo
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2004
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Février 2004
    Messages : 1 259
    Points : 1 937
    Points
    1 937
    Par défaut
    Les objets sont passes par reference: c'est a dire que c'est la reference de l'objet qui est passe en parametre.

    Faire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public void A(String maString)
    {
      maString = "toto";
    }
    Cela remplace la reference pointee par maString par celle de l'objet "toto" mais ca ne peut pas changer la reference passee en argument de la methode.

    Ainsi ce code

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    String s = "tata";
    System.out.println(s);
    A(s);
    System.out.println(s);
    Affichera 2 fois tata, la methode A n'a aucun moyen de modifier la reference contenue dans s, pour cela il aurait fallu passer en parametre l'adresse de la variable s, ce qui n'est pas possible en Java.

    Bulbo
    [Java] [NetBeans] [CVS]
    La FAQ Java
    Merci de ne pas me poser de questions techniques par MP.

  5. #5
    Membre expert Avatar de KiLVaiDeN
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 851
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 851
    Points : 3 480
    Points
    3 480
    Par défaut
    merci

    Petite précision : Dans une méthode, les paramètres sont en effet passé par référence, mais chacune des variables citée en paramètre est localement initialisée.
    K

  6. #6
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2004
    Messages
    882
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2004
    Messages : 882
    Points : 948
    Points
    948
    Par défaut
    Les String sont immutables si tu veux les modifier par référence, tu peux utiliser les classes StringBuffer ou StringBuilder (uniquement sous Java 5)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    private appendTest(StringBuffer sb, String appender){
       if(sb!=null){
          sb.append(appender);
       }
    }
    Exemple d'appel
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    String source = "toto";
    StringBuffer sb = new StringBuffer(source);
    this.appendTest(sb, " is the best");
    System.out.println("Result - " + sb.toString());

    Sun Certified Business Component Developer
    Sun Certified Java Programmer
    --
    The definitive toolbox for GWT applications: gwt-toolbox
    My blog about Java and JEE: Benjamin's Blog

  7. #7
    Membre expert Avatar de KiLVaiDeN
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 851
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 851
    Points : 3 480
    Points
    3 480
    Par défaut
    Salut,

    Benjamin, il manque juste un void en retour de ta méthode :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    private void appendTest(StringBuffer sb, String appender){ 
       if(sb==null){ 
          sb = new StringBuffer(appender); 
       }else{ 
          sb.append(appender); 
       } 
    }
    Pour éviter les confusions
    K

  8. #8
    Membre actif Avatar de xxaragornxx
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    241
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 241
    Points : 253
    Points
    253
    Par défaut
    Citation Envoyé par SEMPERE Benjamin
    Les String sont immutables
    Si tu regardes la source de la classe String, tu peux voir qu'elle est déclarée comme suit:
    public finale class String [...]

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2003
    Messages
    35
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 35
    Points : 25
    Points
    25
    Par défaut
    Citation Envoyé par bulbo
    Les objets sont passes par reference: c'est a dire que c'est la reference de l'objet qui est passe en parametre.

    Faire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public void A(String maString)
    {
      maString = "toto";
    }
    Cela remplace la reference pointee par maString par celle de l'objet "toto" mais ca ne peut pas changer la reference passee en argument de la methode.

    Ainsi ce code

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    String s = "tata";
    System.out.println(s);
    A(s);
    System.out.println(s);
    Affichera 2 fois tata, la methode A n'a aucun moyen de modifier la reference contenue dans s, pour cela il aurait fallu passer en parametre l'adresse de la variable s, ce qui n'est pas possible en Java.

    Bulbo
    euh.. ok, je vois le truc, dans ce cas la ca devrait pouvoir fonctionner en utilisant une variable globale, initialisée a un endroit, et manipulée à un autre.

    De plus, tu dis que "la methode A n'a aucun moyen de modifier la reference contenue dans s"

    est ce que c'est valable pour n'importe quel objet ou est ce simplement valable pour les string ?

    Derniere question :

    J'ai besoin de ce mecanisme pour faire une methode recursive mettant a jour un path. Je pars de la fin du path, et m'arrete au moment ou j'arrive au repertoire Home. Mon code ressemble a ca :

    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
     
     
    public void A(){
       String s = new String(); 
       B(s); 
    }
     
    public void B(String valeur){
     
        valeur = valeur + analyse(); 
     
        if(condition respectee pour recursivite){
            B(valeur); 
        }
    }
    Or dans ce cas, la string valeur est bien mis a jour a chaque passage dans la méthode recursive, on construit bien

    /test

    puis

    repertoire/test

    puis

    home/repertoire/test

    du coup, le fait de faire l'affectation
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     valeur= valeur + analyse();
    ne donne pas l'impression de faire une reaffectation. A moins que je ne me trompe.

  10. #10
    Membre expert Avatar de KiLVaiDeN
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 851
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 851
    Points : 3 480
    Points
    3 480
    Par défaut
    Citation Envoyé par xxaragornxx
    Citation Envoyé par SEMPERE Benjamin
    Les String sont immutables
    Si tu regardes la source de la classe String, tu peux voir qu'elle est déclarée comme suit:
    public finale class String [...]
    Salut,

    Je ne pense pas que ce soit le fait qu'elle soit déclarée "final" qui rende l'objet String immutable.

    C'est plutôt sont coté "native", qui travaille en mémoire, à la manière de C. Un String crée n'est jamais modifié, il est simplement initialisé, après à chaque opération ( concaténation etc ) un nouvel objet String est crée.
    K

  11. #11
    Membre expert Avatar de KiLVaiDeN
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 851
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 851
    Points : 3 480
    Points
    3 480
    Par défaut
    Citation Envoyé par Snivel
    du coup, le fait de faire l'affectation
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     valeur= valeur + analyse();
    ne donne pas l'impression de faire une reaffectation. A moins que je ne me trompe.
    Dans ton cas de récursivité, tu vas créer des objets String à chaque passage, et passer "le nouvel objet" à ta méthode récursive, donc à chaque fois le paramètre sera correcte, par contre dans ta méthode A(); tu auras toujours l'objet initial.
    K

  12. #12
    Membre actif Avatar de xxaragornxx
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    241
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 241
    Points : 253
    Points
    253
    Par défaut
    Citation Envoyé par KiLVaiDeN
    Je ne pense pas que ce soit le fait qu'elle soit déclarée "final" qui rende l'objet String immutable.
    C'est tout de même la signification de ce mot clé:

    Avec un type primitif, final fait de la valeur une constante, mais avec un objet référence, final fait de la « référence » une constante. Une fois la référence liée à un objet, elle ne peut jamais changer pour pointer vers un autre objet. Quoiqu'il en soit, l'objet lui même peut être modifié
    Donc dans la conception même de la classe "l'immutabilité" est là.
    Après dans son implémentation...

  13. #13
    Rédacteur
    Avatar de bulbo
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2004
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Février 2004
    Messages : 1 259
    Points : 1 937
    Points
    1 937
    Par défaut
    tu dis que "la methode A n'a aucun moyen de modifier la reference contenue dans s"
    C'est valable pour tout objet, c'est le principe du passage par reference.

    Si tu veux modifier ton parametre en retour tu peux passer par une classe Holder par exemple:

    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
    public class StringHolder
    {
      public String value;
     
      public StringHolder(String aString)
      {
        value = aString;
      }
    }
     
    ....
     
    public void A(StringHolder sh)
    {
      sh.value = "toto";
    }
     
    ....
    String s = "tata";
    StringHolder holder = new StringHolder(s);
    A(holder);
    s = holder.value;
    Pour ce qui est de ton code recursif c'est normal qu'il fonctionne, tu ne cherches pas a exploiter la valeur modifiee du parametre apres l'appel recursif donc tout va bien.

    Lorsque tu ecris valuer = valeur + analyse, tu reference une nouvelle string, cette string n'est pas visible de la methode appelante mais peut l'etre dans l'appel recursif, rien d'etrange donc.

    Bulbo
    [Java] [NetBeans] [CVS]
    La FAQ Java
    Merci de ne pas me poser de questions techniques par MP.

  14. #14
    Membre expert Avatar de KiLVaiDeN
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 851
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 851
    Points : 3 480
    Points
    3 480
    Par défaut
    Avec un type primitif, final fait de la valeur une constante, mais avec un objet référence, final fait de la « référence » une constante. Une fois la référence liée à un objet, elle ne peut jamais changer pour pointer vers un autre objet. Quoiqu'il en soit, l'objet lui même peut être modifié
    Ils parlent d'une constante, mais lorsque le mot clé "final" est utilisé pour déclarer une classe, le sens est "que cette classe ne pourra pas être spécialisée".
    Voir ce lien
    K

  15. #15
    Membre actif Avatar de xxaragornxx
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    241
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 241
    Points : 253
    Points
    253
    Par défaut
    Citation Envoyé par KiLVaiDeN
    Avec un type primitif, final fait de la valeur une constante, mais avec un objet référence, final fait de la « référence » une constante. Une fois la référence liée à un objet, elle ne peut jamais changer pour pointer vers un autre objet. Quoiqu'il en soit, l'objet lui même peut être modifié
    Ils parlent d'une constante, mais lorsque le mot clé "final" est utilisé pour déclarer une classe, le sens est "que cette classe ne pourra pas être spécialisée".
    Voir ce lien
    Oui, c'est vrai, j'étais parti sur la notion d'objet et non de classe.. Erreur de débutant

  16. #16
    Rédacteur
    Avatar de bulbo
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2004
    Messages
    1 259
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Février 2004
    Messages : 1 259
    Points : 1 937
    Points
    1 937
    Par défaut
    Citation Envoyé par xxaragornxx
    Citation Envoyé par KiLVaiDeN
    Je ne pense pas que ce soit le fait qu'elle soit déclarée "final" qui rende l'objet String immutable.
    C'est tout de même la signification de ce mot clé:

    Avec un type primitif, final fait de la valeur une constante, mais avec un objet référence, final fait de la « référence » une constante. Une fois la référence liée à un objet, elle ne peut jamais changer pour pointer vers un autre objet. Quoiqu'il en soit, l'objet lui même peut être modifié
    Donc dans la conception même de la classe "l'immutabilité" est là.
    Après dans son implémentation...
    Immutable signifie qui ne peut etre change. Le fait de definir String final empeche d'heriter de String pour en redefinir le comportement ce qui n'est pas la meme chose.

    Une classe genre Vector declaree final n'est pas immutable puisqu'il est possible de modifier l'objet en faisant des add ou des remove par exemple.

    Immutable signifie que le seul moyen d'obtenir un objet different et d'en creer un autre et pas de modifier un existant deja.

    Bulbo
    [Java] [NetBeans] [CVS]
    La FAQ Java
    Merci de ne pas me poser de questions techniques par MP.

  17. #17
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2004
    Messages
    882
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2004
    Messages : 882
    Points : 948
    Points
    948
    Par défaut
    Citation Envoyé par KiLVaiDeN
    Salut,

    Benjamin, il manque juste un void en retour de ta méthode :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    private void appendTest(StringBuffer sb, String appender){ 
       if(sb==null){ 
          sb = new StringBuffer(appender); 
       }else{ 
          sb.append(appender); 
       } 
    }
    Pour éviter les confusions
    Effectivement

    Sun Certified Business Component Developer
    Sun Certified Java Programmer
    --
    The definitive toolbox for GWT applications: gwt-toolbox
    My blog about Java and JEE: Benjamin's Blog

  18. #18
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2003
    Messages
    35
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 35
    Points : 25
    Points
    25
    Par défaut
    ok, merci pour les infos, j'ai pu resoudre mon probleme. Je pensais a tort pouvoir faire comme en C.

Discussions similaires

  1. Passage de valeur par reference
    Par psmpa dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 05/03/2009, 16h22
  2. Eviter Passage de Paramétres par reference
    Par eric1970 dans le forum Débuter avec Java
    Réponses: 1
    Dernier message: 25/02/2009, 22h03
  3. passage de <this> par reference
    Par eKinai dans le forum C#
    Réponses: 7
    Dernier message: 22/01/2007, 12h00
  4. Le passage de paramètres par REFERENCES
    Par yohann_ dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 25/01/2006, 19h47
  5. [String] passage d'objet par référence
    Par adilou1981 dans le forum Langage
    Réponses: 8
    Dernier message: 01/04/2005, 15h22

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