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

Java Discussion :

Java & Autoboxing


Sujet :

Java

  1. #1
    Nouveau membre du Club
    Inscrit en
    Janvier 2009
    Messages
    46
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 46
    Points : 25
    Points
    25
    Par défaut Java & Autoboxing
    Bonjour à tous,

    Je fais appel à vos talents pour m'expliquer ce qui se passe dans le bout de code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Integer i1 = 1000;
    	Integer i2 = 1000;
    	if(i1 != i2) System.out.println("i1 non égal à i2");
     
    	Integer i3 = 127;
    	Integer i4 = 127;
    	if(i3 != i4) System.out.println("i3 non égal à i4");
    A l'exécution il m'affiche bien "i1 non égal à i2". Jusque la d'accord, puisque i1 et i2 sont 2 objets différents, et ce sont ici les références qui sont comparées.

    Cependant à ma grande surprise, il n'affiche pas "3 non égal à i4" !
    Par contre si je fixe la valeur des variables i3 et i4 à 128 (au lieu de 127), la il m'affiche bien "i3 non égal à i4" !

    Conclusion, si 2 Integer sont égaux et inférieurs à 128, java les considére égaux. Cependant si ils sont supérieurs à 128, ils ne sont plus égaux...

    Si quelqu'un peut m'éclairer...

  2. #2
    Membre chevronné
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Points : 1 984
    Points
    1 984
    Par défaut
    Au risque de te surprendre je dirais que ton résultat est... normal

    En fait, la classe Integer utilise un cache pour les Integer entre -128 et 127. C'est ce qui explique le comportement que tu observes... Pour les Integer hors de ces bornes, c'est une création d'objet différent.

    J'ajouterais que l'autoboxing fait appel a la fonction de la classe Integer :
    public static Integer valueOf(int i)

    Et si tu regardes sa source, tu verras le code correspondant au cache

    a+

  3. #3
    Nouveau membre du Club
    Inscrit en
    Janvier 2009
    Messages
    46
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 46
    Points : 25
    Points
    25
    Par défaut
    Bon je répond moi même à ma question...

    Java crée par défaut un pool d'Integer, compris entre les valeurs -127 et 127, et ce afin d'économiser la mémoire.

    Et donc quand on instancie un Integer dans cette plage, on ne crée par de nouvelle objet, mais la référence pointe vers la valeur déja stockée dans le pool de connexion.

    Donc Integer(127) et Integer(127) ont les mêmes adresses mémoires. Contrairement à Integer(128) et Integer(128).


    edit@hwoarang : effectivement, tu m'as devancé, et je n'avais pas pris assez de temps pour chercher, merci

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par romano62880 Voir le message

    Donc Integer(127) et Integer(127) ont les mêmes adresses mémoires. Contrairement à Integer(128) et Integer(128).
    Attention, new Integer(127) et new Integer(127) ont bien des adresses différentes. C'est Integer.valueOf(127) qui fait appel à une cache!

  5. #5
    Membre confirmé

    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2011
    Messages
    181
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2011
    Messages : 181
    Points : 519
    Points
    519
    Billets dans le blog
    1
    Par défaut
    slt,
    Pour tester les deux entiers essaye la méthode intValue () de la class Integer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Integer i1 = 1000;
    	Integer i2 = 1000;
    	if (i1.intValue () != i2.intValue ()) System.out.println("i1 non égal à i2");
    	Integer i3 = 127;
    	Integer i4 = 127;
    	if(i3.intValue () != i4.intValue ()) System.out.println("i3 non égal à i4");
    Ce que tu a fait toi, c'est crée deux instances de la class Integer, en les initialisant, tu a modifié les valeurs de chacun de leurs attributs value, qui est de type int, (i1.value == 1000, i2.value == 1000), ensuite, si tu fait Tu vas tester les deux references des instances, i1 et i2, par contre si tu met, i1.intValue (), la méthode intValue () vas retournée la valeur contenue dans l’attribue value de l'instance i1, donc tester deux entier, pas deux references des instances de la class Integer .
    A+ .

  6. #6
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Citation Envoyé par mohamine1989 Voir le message
    Pour tester les deux entiers essaye la méthode intValue ()
    Oui, ou equals(), comme à chaque fois qu'on veut comparer des objets.
    Mais là la question c'était pas s'il fallait utiliser == ou autre chose, mais pourquoi des fois les objets c'est les mêmes et des fois pas. Une sorte de curiosité scientifique.

    Citation Envoyé par mohamine1989 Voir le message
    Ce que tu a fait toi, c'est crée deux instances de la class Integer, en les initialisant, tu a modifié les valeurs de chacun de leurs attributs value, qui est de type int, (i1.value == 1000, i2.value == 1000), ensuite, si tu fait Tu vas tester les deux references des instances, i1 et i2, par contre si tu met, i1.intValue (), la méthode intValue () vas retournée la valeur contenue dans l’attribue value de l'instance i1, donc tester deux entier, pas deux references des instances de la class Integer .
    J'ai pas trop compris ce que tu essaies de dire, mais, comme nous l'avons vu, il a créé trois instances de la classe Integer, pas deux, pas quatre.
    Et Integer étant une classe immutable on ne peut pas changer la valeur de son attribut value après que l'objet a été instancié.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Nouveau membre du Club
    Inscrit en
    Janvier 2009
    Messages
    46
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 46
    Points : 25
    Points
    25
    Par défaut
    Merci pour vos réponses.

    Tout comme le dit thelvin, je ne cherchais pas ici à tester 2 entiers, je me posais simplement la question, à savoir pourquoi quand on crée deux objets Integer(127), ceux-ci avaient la même adresse mémoire, et pourquoi quand on en crée 2 Integer(128) ceux-ci avaient des adresses différentes.
    Je sais bien qu'en utilisant equals() ou intValue() il compare la valeur de l'entier.

    @tchize_ : tu fais erreur, deux objets new Integer(127) et new Integer(127) ont bien la même adresse mémoire ! C'est ce qu'on vient d'expliquer.

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par romano62880 Voir le message
    @tchize_ : tu fais erreur, deux objets new Integer(127) et new Integer(127) ont bien la même adresse mémoire ! C'est ce qu'on vient d'expliquer.
    Non ce serait contraire au langage java et si tu teste tu verra que ce n'est pas le cas. Ce qu'on viens d'expliquer c'est que l'autoboxing fait appel à Integer.valueOf() et que cette méthode utilise un cache pour le range correspondant aux bytes. Integer est une classe comme une autre, elle n'est pas native et ne bénéficie d'aucun traitement de faveur dans la jvm.

  9. #9
    Membre chevronné
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Points : 1 984
    Points
    1 984
    Par défaut
    Citation Envoyé par romano62880 Voir le message
    @tchize_ : tu fais erreur, deux objets new Integer(127) et new Integer(127) ont bien la même adresse mémoire ! C'est ce qu'on vient d'expliquer.
    Non, ce n'est pas ce qu'on vient d'expliquer. Quand tu fais Integer i = 5; ca revient à faire Integer i = Integer.valueof(5); et pas Integer i = new Integer(5);
    Or le cache est géré dans la fonction valueof.

    Meme pour les objets immutable, faire un new renvoie toujours une nouvelle instance de l'objet (meme pour string, integer, ...)

  10. #10
    Nouveau membre du Club
    Inscrit en
    Janvier 2009
    Messages
    46
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 46
    Points : 25
    Points
    25
    Par défaut
    Pardons je m'exprime mal, je sais que chaque variable en java a une adresse mémoire distincte, je voulais dire que dans le cas ou on fait 2 new Integer(127), la valeur des 2 variables est la même, c'est à dire qu'elle pointe vers la même adresse mémoire.

    Je me suis amusé a regarder le code de Integer.valueOf :

    public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high)
    return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
    }

    On voit que Integer.valueOf(i) dans le cas ou i est entre IntegerCache.low et IntegerCache.high, retournera toujours le même Objet pour une même valeur de i.

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par romano62880 Voir le message
    dans le cas ou on fait 2 new Integer(127), la valeur des 2 variables est la même, c'est à dire qu'elle pointe vers la même adresse mémoire.
    Mais non!

  12. #12
    Membre chevronné
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Points : 1 984
    Points
    1 984
    Par défaut
    Citation Envoyé par romano62880 Voir le message
    Pardons je m'exprime mal, je sais que chaque variable en java a une adresse mémoire distincte, je voulais dire que dans le cas ou on fait 2 new Integer(127), la valeur des 2 variables est la même, c'est à dire qu'elle pointe vers la même adresse mémoire.
    Non. Je ne vois pas comment etre plus clair que :
    Citation Envoyé par hwoarang Voir le message
    Quand tu fais Integer i = 5; ca revient à faire Integer i = Integer.valueof(5); et pas Integer i = new Integer(5);
    Or le cache est géré dans la fonction valueof.

  13. #13
    Nouveau membre du Club
    Inscrit en
    Janvier 2009
    Messages
    46
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 46
    Points : 25
    Points
    25
    Par défaut
    Humm.. décidément je ne comprend pas ou vous voulez en venir.
    Désolé, au risque d'être "lourd" je vous montre mon raisonnement :

    Je suis d'accord avec toi hwoarang, quand on fait :
    Integer i = 5, cela équivaut en fait avec Integer i = Integer.valueOf(5);
    Et Integer.valueOf(5) qui retourne l'objet Integer(5) qu'il y a dans le cache.


    Je vais partir de l'exemple suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Integer i1 = Integer.valueOf(5);
    Integer i2 = Integer.valueOf(5);
    System.out.println(i1 == i2);
     
    Integer i3 = Integer.valueOf(128);
    Integer i4 = Integer.valueOf(128);
    System.out.println(i3 == i4);
    Résultat du code ci-dessus : true puis false.
    Donc dites moi si vous êtes d'accord avec moi : dans le cas d'une comparaison via "==", comme nous sommes ici sur des objets (et non des types primitifs), ce sont les adresses référencées par les variables qui sont testées. Et donc les objets "Integer" présents dans le heap.

    La compasaison i1 == i2 retourne true, ce qui montre bien que ce sont les 2 variables référencent bien le même objet dans le heap.
    La comparaison i3 = i4 retourne false, ce qui montre que ce sont 2 objets différents du heap.

    A quel niveau suis-je dans l'erreur ?

  14. #14
    Nouveau membre du Club
    Inscrit en
    Janvier 2009
    Messages
    46
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 46
    Points : 25
    Points
    25
    Par défaut
    alleluyah je viens de comprendre ce que vous vouliez dire !

    C'est fin de semaine ne m'en voulez pas

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par romano62880 Voir le message

    A quel niveau suis-je dans l'erreur ?
    Quand tu prétends que c'est aussi valable avec les new Integer():

    Citation Envoyé par romano62880
    dans le cas ou on fait 2 new Integer(127), la valeur des 2 variables est la même, c'est à dire qu'elle pointe vers la même adresse mémoire.

  16. #16
    Nouveau membre du Club
    Inscrit en
    Janvier 2009
    Messages
    46
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 46
    Points : 25
    Points
    25
    Par défaut
    Oui, je n'avais pas compris ce que tu voulais dire.
    Que quand on fait Integer i1 = new Integer(5), il ne va pas chercher la valeur dans le cache contrairement à quand on fait Integer i2 = 5 (la l'autoboxing appel Integer.valueOf(5) et récupére depuis le cache).

    Encore désolé et merci pour les explications !
    Je passe la certification SCJP d'ici fin d'année

  17. #17
    Membre chevronné
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Points : 1 984
    Points
    1 984
    Par défaut
    Citation Envoyé par romano62880 Voir le message
    C'est fin de semaine ne m'en voulez pas
    Pas de mal


    Citation Envoyé par romano62880 Voir le message
    Je passe la certification SCJP d'ici fin d'année
    Bon courage

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

Discussions similaires

  1. Service de nommage java C++
    Par Anonymous dans le forum CORBA
    Réponses: 3
    Dernier message: 15/04/2002, 12h48

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