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 :

Trouble avec String Immutable


Sujet :

Langage Java

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    122
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Mars 2006
    Messages : 122
    Par défaut Trouble avec String Immutable
    Salut,

    J'ai ete a un entretien et l'une des questions ressemblait a ceci (je passe les tests du meme genre sur String avec equals et l'utilisation de new):

    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
    public class TestString {
       public static void main(String[] args) {
          String t1 = "France";
          String t2 = t1 + " Mexique";
          String t3 = t1 + " Mexique";    
     
          String t4 = "France" + " Mexique";
          String t5 = "France" + " Mexique";
     
          if(t2 == t3)
             System.out.println("Equals"); 
          else
             System.out.println("Not Equals"); //Resultat affiche
     
          if(t4 == t5)
             System.out.println("Equals"); //Resultat affiche
          else
             System.out.println("Not Equals");
       }
    }
    Je me dis sur le coup, vu qu'un String ne peut pas changer, t2 et t3 pointent forcement sur le meme objet, donc le 1er test afficherait "Equals". Ce n'est pourtant pas le cas, et j'ai un peu de mal à m'expliquer pourquoi, surtout quand on voit que le 2nd test renvoie "Equals" comme prevu. Pourquoi t2 et t3 pointent ils sur des objets differents ?

    Merci d'avance de votre aide.

    Nuriel

  2. #2
    Membre confirmé Avatar de r2d2abc
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    212
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 212
    Par défaut
    Salut, Immutable signifie not mutable (!mutable (String,Integer,, type primitifs)) c'est à dire que l'attribut devient une constante une fois initialisée et ne peut donc être modifiée (eq final devant une déclaration). Ajouter des constantes entre elles et les assigner à deux variables donne une constante donc une réference unique, donc les 2 variables pointent sur la même valeur, donc égalité vraie, tout autre cas multiplie les instances donc des tests d'équivalence faussés.
    http://gfx.developpez.com/tutoriel/java/strings/
    hth...

  3. #3
    Invité
    Invité(e)
    Par défaut
    Salut,

    Ici ce comportement est explicable comme suit: Pour les chaines un pool est utilisé pour ne pas réinstantier une chaine si le compilateur peut déterminer statiquement que le résultat est le même. Dans le cas où tu concatènes deux litéraux chaines "France" + "Mexique", le compilateur est sûr que le résultat est le même dans les deux cas, donc la même instance sera référencée.
    L'analyse statique exécutée par le compilo Java est plutôt sommaire étant donné que la VM s'occupe de vraiment optimiser, donc dans l'autre cas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
     String t1 = "France";
     String t2 = t1 + " Mexique";
     String t3 = t1 + " Mexique";
    L'utilisation de t1 fait que le compilo n'est plus capable de déterminer que t1 n'a pas été changé entre les deux utilisations. Une analyse statique plus poussée (dans ce cas une analyse du flux de contrôle montrerait tout de suite que t1 n'est pas modifié et on pourrait même inliner, mais ça changerait beaucoup le comportement habituel du compilo et pourrait conduire à des résultats inattendus) pourrait permettre de le déterminer, mais le compilo ne fait pas la différence entre ce cas et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     String t1 = "France";
     String t2 = t1 + " Mexique";
     t1 = "Allemagne";
     String t3 = t1 + " Mexique";
    Et donc deux instances différentes sont utilisées pour t2 et t3.
    J'espère avoir été clair

    A plus

  4. #4
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    je rajoute que poser cette question à un entretiens, à moins qu'on demande un programmeur java avec 5 ans d'expérience effective, c'est du chipo n'importe nawak C'est vraiment pour dire de ne finir avec aucun candidat si toutes les questions étaient dans le même accabi D'ailleurs un "bon" candidat répondrait que, de toutes façons, on ne compare pas des String avec == sauf si on veux risquer de foutre en l'air le code au moindre changement


    Je rajouterais que le comportement d'égalité dans le cas où les string ont statiquement pu être analysée commé étant égales, n'est pas nécessairement le même d'un compilateur à l'autre. Certe le compilo de oracle le fait, mais d'autre compilateurs pourraient ne pas le faire, ou, à l'inverse, pourraient aussi le faire dans l'autre cas.

  5. #5
    Membre Expert
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Par défaut
    Perso, j'aurais répondu que ca depend de la gestion de la memoire par la VM (faut pas oublier que l'un des plus gros interet de java est l'aspect multi-plateforme donc il vaut mieux eviter le code spécifique qui marchera sur tel version sur tel OS et pas sur tel autre) et que si on veut tester si 2 chaines sont identiques, il faut utiliser Object.equals...

  6. #6
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    rien à voir avec la gestion de la mémoire par la jvm, les règle de la jvm sont les même pour tout le monde ^^. Quand tu fais un new t'as un nouvel objet et donc == dira false. C'est le compilateur qui, pour le code monté plus haut, choisi où et comment il place ses new

  7. #7
    Membre Expert
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    rien à voir avec la gestion de la mémoire par la jvm, les règle de la jvm sont les même pour tout le monde ^^. Quand tu fais un new t'as un nouvel objet et donc == dira false. C'est le compilateur qui, pour le code monté plus haut, choisi où et comment il place ses new
    Tu es sur que ca fait partie des "requirements" le fait de ne pas duppliquer les immutables ? Je n'ai pas vérifié mais je ne pensais pas que les spécifications des VM allaient si loin.

  8. #8
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    immutable ou pas, c'est la même chose, les requirement disquent jsute ce qu'il faut faire avec les new, les instances etc en général. Il n'y a pas d'exception du genre "si je fais un new avec un immutable alors je vais plutot chercher un déjà existant avec la même valeur". ça, c'est la popote du compilateur qui, en très gros, à partir de ce code

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    String s =  "1234567"+" violette";
    Integer i = 1+3;

    mettra dans le bytecode


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    String s = "1234567 violette"
    Integer i = new Integer(4);
    ou mettra

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    String s = "1234567 violette".intern();
    Integer i = Integer.valueOf(4);
    Bon c'est qu'un exemple là, mais disons que pour ces optimisations là, c'est le compilateur qui joue, pas la JVM. Un bytecode doit se comporter de la même manière quelle que soit les optimisations qu'y font la jvm, la jvm n'a pas liberté de faire des optimisations qui changeraient la sortie du bytecode. Maintenant il y a aussi l'api dans la jvm qui peut changer de comportement d'une version à l'autre, mais c'est une autre histoire

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    122
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Mars 2006
    Messages : 122
    Par défaut
    Bon ben une autre dimension de Java que je vais devoir explorer. Merci de vos reponses en tout cas. Si j'ai bien compris, tout depend de comment de compilateur transforme le code. Quelle application recommandez vous pour voir exactement ces transformations ?

  10. #10
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Hmm, en fait, un compilateur Java valide n'a pas tellement de libertés que ça.

    Les spécifications Java disent clairement que :
    - Si c'est une expression constante, le compilateur doit l'évaluer lui-même et faire comme si c'était un littéral String (qui donc sera dans le pool de String.)
    - Sinon, l'expression doit produire une String nouvellement créée (autrement dit qui n'est encore référencée par rien du tout. Bref ça doit faire comme un new)

    Dans le cas t2 et t3, les expressions sont constituées d'une opérande String littérale, et d'une opérande String variable. Ce n'est pas une expression constante => le compilateur peut faire toutes les analyses statiques qu'il veut, mais le code doit produire deux objets String distincts.

    Dans le cas t4 et t5, les expressions sont constituées de deux opérandes String littérales. C'est une expression constante => le compilateur doit calculer la String lui-même et faire comme si c'était un littéral. Ce sera donc une seule String, tirée du pool.

    Mais bon, au quotidien, je trouve pas très utile de savoir ça. Je préfère la règle simple "On utilise equals() pour être sûr" et relire les specs dans les cas où on veut gagner du temps en comparant des String tirées du pool.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    122
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Mars 2006
    Messages : 122
    Par défaut
    Chapeau bas. Confirme ici. Mais comment tu fais pour savoir des trucs pareils ? Meme en l'ayant lue, je ne suis meme pas sur que ca m'aurait marque au point de m'en souvenir. M'enfin, ce n'est pas tres utile dans le java de tous les jours, et il parait qu'en dessous de 5 ans d'experience, c'est pas grave Je m'en vais de ce pas reviser pour mes autres entretiens. Merci a tous.

    PS: Je passe en resolu ce soir, mais juste pour savoir, ca vous arrive souvent de plonger dans les specs ? Parce que pour moi, a part l'API et des tutos specifiques... Je commence a me demander si c'est assez pour avoir des bases plus que solides.

  12. #12
    Membre chevronné
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    476
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 476
    Par défaut
    on ne compare pas des String avec == sauf si on veux risquer de foutre en l'air le code au moindre changement
    100% d'accord.

    je rajoute que poser cette question à un entretiens, à moins qu'on demande un programmeur java avec 5 ans d'expérience effective, c'est du chipo n'importe nawak
    Tu oublies les certifs
    Une fois des bonnes bases en java (1-2 ans en entreprise) , tu passes la SCJP sérieusement (pas juste pour avoir le minimum pour l'obtenir) et tu sais ça et d'autres trucs.
    En tous les cas, c'est ce que j'ai fait.

    Citation Envoyé par nuriel2 Voir le message
    PS: Je passe en resolu ce soir, mais juste pour savoir, ca vous arrive souvent de plonger dans les specs ? Parce que pour moi, a part l'API et des tutos specifiques... Je commence a me demander si c'est assez pour avoir des bases plus que solides.
    Si t'as du temps et un peu d'argent, je te conseille justement de passer la certification SCJP. Je l'ai passé il y a bientôt 2 ans, ca t'apprend des trucs super utiles dans les dév de tous les jours et aussi quelques trucs tordus comme ca
    Remarque, tu peux aussi potasser l'exam sans le passer mais ca serait dommage de partir sans un mignon petit certificat

    Le livre que j'ai utilisé (magnifique ), à la différence que c'était pour la version 5 de java:

  13. #13
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Citation Envoyé par thebloodyman Voir le message

    Tu oublies les certifs
    Une fois des bonnes bases en java (1-2 ans en entreprise) , tu passes la SCJP sérieusement (pas juste pour avoir le minimum pour l'obtenir) et tu sais ça et d'autres trucs.
    En tous les cas, c'est ce que j'ai fait.
    D'accord avec toi, mais concrètement, dans ton job de programmeur, ça t'apporte quoi et ça apporte quoi à ton recruteur de savoir que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Integer a = 69;
    Integer b = 69;
    Integer c = 6969;
    Integer d = 6969;
    //a==b -> true
    //c==d -> false
    Je préfère 100 fois un gars capable de me pondre un algo clair et compréhensible par toute l'équipe en 30 minutes avec les tests unitaire ad hoc, que quelqu'un qui va pourrir le code en jouant sur les coté extrèmes de la jvm et qu'il faudra consulter 3 fois les spécification au fond de la jvm pour être sur de comment marche le code. C'est pour ça que, avis personnel, ce genre de question n'a pas sa place en interview, sauf poste très pointu où t'es prêt à payer le prix.

  14. #14
    Membre chevronné
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    476
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 476
    Par défaut
    Tu prêches un convaincu
    D''où mon approbation "100% d'accord " sur ta remarque :
    on ne compare pas des String avec == sauf si on veux risquer de foutre en l'air le code au moindre changement
    On a pas forcément un "bon" développeur qui fera un code clair et maintenable, mais plutôt quelqu'un d'expérimenté et ou de motivé.
    C'est peut-être ce que certaines boites recherches. Qui sait...

    Comme je dis souvent à ceux qui génèrent de la complexité sans valeur dans leur code
    "je suis bête, alors je veux travailler sur un code lisible, simple et peu sujet à l'erreur."
    Integer a = 69;
    Integer b = 69;
    Integer c = 6969;
    Integer d = 6969;
    //a==b -> true
    //c==d -> false
    Je viens de tester : incroyable
    Et quelle en est la raison ???

    C'est vrai que hors cas très spécifiques (méthode equals(Objet o), valeur de retour d'une méthode mockée, singleton...), je ne me risque pas à utiliser l'identité mémoire pour comparer 2 références.

  15. #15
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    le compilateur utilise Integer.valueOf() (cf mon postp lus haut) et cette méthode a un cache avec tous les entiers entre -128 et +127

  16. #16
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Au passage, ça, je ne crois pas que ce soit requis par la JSTL ni la JavaDoc. Je suppose qu'on peut tomber sur une implémentation valide qui génère des résultats différents.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  17. #17
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    pour les entiers à petite valeur(code que j'ai montré), le comportement est forcé par le java langage specifications, dans les règles relatives à l'autoboxing:
    If the value p being boxed is true, false, a byte, a char in the range \u0000 to \u007f, or an int or short number between -128 and 127, then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2.
    Pour les entiers à grande valeurs, le comportement dépendra de la jvm:
    Less memory-limited implementations might, for example, cache all characters and shorts, as well as integers and longs in the range of -32K - +32K

    Quand aux String, il est stipulé, section 3.10.5
    String literals-or, more generally, strings that are the values of constant expressions (§15.28)-are "interned" so as to share unique instances, using the method String.intern

  18. #18
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Ah bah oui, tiens. Merci pour l'info.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  19. #19
    Membre Expert
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Par défaut
    Merci pour l'info. Mais moralité: il vaut mieux utiliser Object.equals()

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. strlen et strcpy non reconnu avec string.h
    Par wolflinger dans le forum C++
    Réponses: 17
    Dernier message: 21/02/2006, 13h44
  2. [RegEx]Probleme avec String.split
    Par sebastieng dans le forum Collection et Stream
    Réponses: 3
    Dernier message: 09/02/2006, 21h24
  3. Trouble avec Excel avec un programme qui utilise un Hook.
    Par hot_metal dans le forum Windows
    Réponses: 5
    Dernier message: 14/01/2006, 13h40
  4. Erreur compilation avec <string>
    Par seal3 dans le forum SL & STL
    Réponses: 9
    Dernier message: 25/08/2005, 20h41
  5. [Struts][logic:iterate] Probleme avec String
    Par julienOriano dans le forum Struts 1
    Réponses: 7
    Dernier message: 15/06/2004, 09h39

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