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 :

Afficher une alerte en cas d'utilisation potentiellement erronée de l'opérateur ==


Sujet :

avec Java

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 41
    Points : 25
    Points
    25
    Par défaut Afficher une alerte en cas d'utilisation potentiellement erronée de l'opérateur ==
    Bonjour,

    Dans ce morceau de code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
            Integer a = 0;
            Integer b = 0;
            while (a == b) {
                System.out.println("a=" + a + ", b=" + b + "\t" + (a == b) + "\t" + (a.equals(b)));
                a++;
                b++;
            }
            System.out.println("a=" + a + ", b=" + b + "\t" + (a == b) + "\t" + (a.equals(b)));
    Je sais pertinemment qu'il faut exclusivement utiliser le .equals() sur des types de variables non primitives mais pourtant, ca m'arrive encore d'utiliser par erreur ce canonique ==

    Ce qui m’énerve le plus, c'est que ce morceau de code va fonctionner jusqu'à la 128ème itération de la boucle, et ce sans erreurs, sans warnings aucun, puis ne plus fonctionner à la 129ème !

    S'il ne faut pas utiliser le == sur autre chose que des primitifs, pourquoi mon IDE (NetBeans en l’occurrence) n'est pas capable de me le rappeler ?

    Une idée du pourquoi et du comment ?

    Merci d'avance.

  2. #2
    Membre expert
    Avatar de MarieKisSlaJoue
    Homme Profil pro
    Ingénieur Cloud
    Inscrit en
    Mai 2012
    Messages
    1 145
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Roumanie

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

    Informations forums :
    Inscription : Mai 2012
    Messages : 1 145
    Points : 3 654
    Points
    3 654
    Billets dans le blog
    20
    Par défaut
    S'il ne faut pas utiliser le == sur autre chose que des primitifs, pourquoi mon IDE (Netbeans en l’occurrence) n'est pas capable de me le rappeler ?
    Non, tu peux très bien utiliser le == sur autre chose que des primitifs. Il n'aura juste pas la même signification que sur les types primitifs... Je ne vois pas ce que tu veux que NetBeans te prévienne. Ca reste du code tout à fait valide avec une vraie utilité derrière.
    Ce post à été écrit par un panda
    Apollo 11 - AGC revue de code
    -- qwerty keybord

  3. #3
    Modérateur
    Avatar de wax78
    Homme Profil pro
    Chef programmeur
    Inscrit en
    Août 2006
    Messages
    4 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chef programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 4 073
    Points : 7 978
    Points
    7 978
    Par défaut
    C'est vrai qu'il y'a de quoi se casser les dents (et j'aurais surement paniquer en voyant ce resultat).

    Il est dit ici http://docs.oracle.com/javase/specs/...html#jls-5.1.7 qu'apparement on est garantit pour les valeur de -128 a 127 (question de cache si je ne m'abuse). Donc le mieux apparement est de toujours utiliser equals (mais je trouve ca vraiment foireux).
    (Les "ça ne marche pas", même écrits sans faute(s), vous porteront discrédit ad vitam æternam et malheur pendant 7 ans)

    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  4. #4
    Membre chevronné Avatar de jeffray03
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2008
    Messages
    1 501
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 501
    Points : 2 120
    Points
    2 120
    Par défaut
    salut,
    c´est a cause du cache.
    ref: lien ou en francais: http://www.java-freelance.fr/java/revues-de-code-i

    Eric

  5. #5
    Membre confirmé Avatar de Satch
    Homme Profil pro
    Hypnothérapeute - Magicien
    Inscrit en
    Mars 2004
    Messages
    498
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Suisse

    Informations professionnelles :
    Activité : Hypnothérapeute - Magicien

    Informations forums :
    Inscription : Mars 2004
    Messages : 498
    Points : 645
    Points
    645
    Par défaut
    wrappers

    Je préférais sincèrement quand il n'y a pas d'autoboxing !
    Je sais que désormais vivre est un calembour,
    La mort est devenue un état permanent,
    Le monde est aux fantômes, aux hyènes et aux vautours.
    Moi je vous dis bravo et vive la mort.

  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 MarieKisSlaJoue Voir le message
    Non, tu peux très bien utiliser le == sur autres chose que des primitifs. Il n'aura juste pas la même signification que sur les type primitif... Je ne vois pas ce que tu veux que Netbeans te prévienne. Ca reste du code tous à fait valide avec une vrai utilité derrière.
    Personnellement, je ne trouve pas que pouvoir faire == sur des types wrapper serve à quoi que ce soit, à part pour écrire du code de test où on pourrait envisager une annotation qui prévient du fait qu'on va le faire volontairement.

    Findbugs permet de prévenir quand on fait ça. Ce serait utile qu'un IDE le fasse directement à la compil.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 41
    Points : 25
    Points
    25
    Par défaut
    Je dois mal m'y prendre (comprenez coder) alors !

    J'ai commencé il y a pas mal d'années maintenant par du C, variables hyper typées (comme vous le savez bien entendu), et mes IDE de l'époque n'avaient pas la souplesse de ceux d'aujourd'hui en ce qui concerne le debug...
    Grosse pause puis je découvre java, et peu après la POO, ainsi que des IDE qui aurait fait ma joie quelques années auparavant.
    J'ai pris pour habitude de n'utiliser que des variables "Objets" que vous appelez wrappers, pour leur "simplicité", pour homogénéiser mes codes, et pour ne pas me faire... enfin vous avez saisi ;-)

    Après cette douche froide (Cf l'extrait de code en début de post), j'essaye de me remettre en question, en vous en posant justement :
    - Est-ce une bonne chose de n'utiliser que des wrappers ? (avec toutes les mécaniques de développement qu'il me faudra garder à l'esprit, comme Integer(2).intValue() =? Integer(2).intValue(), au lieu de 2=?2...)
    - Vous limitez-vous à l'utilisation très anecdotique de ces wrappers ?

    Je vous pose ces questions car je viens à me demander si je ne dois pas changer mon fusil d'épaule en ce qui concerne ces variables : le gain en "simplicité" me parait maintenant dérisoire si cela nécessite du code, pas forcement compliqué, en plus pour tester 2=?2, cela alourdi considérablement le code.

    Quelle est la règle de l'art selon vous ?

    @MarieKisSlaJoue : ok en ce qui concerne == entre objet, ce qui me dérange le plus, c'est le comportement différent en fonction d'une limite de chiffre... il n'y a pas d'unicité de fonctionnement. En ce qui me concerne, je trouve ca absolument dangereux de laisser paraitre que 2=2, mais que 129!=129, du coup je pense que, comme Satch, c'est une hérésie l'autoboxing (merci d'ailleurs, je ne connaissais pas le terme)
    @thelvin : pour tester si deux objects sont en fait les mêmes, ca peut servir en effet, mais je pense (comme toi, à moins de ne pas avoir compris ton propos) que cela reste rare, je ne vois que l'override de compareTo() en fait...
    @Autres : Merci pour les liens, je dormirais avec moins de dents, certes, mais un peu moins bête ;-)

  8. #8
    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,


    Le problème ne vient pas directement de l'autoboxing, mais de la syntaxe du langage.

    L'opérateur == a deux significations différentes selon qu'on l'utilise sur des types primitifs ou des objets.
    • Il permet de vérifier l'égalité des types primitifs.
      Si a et b sont deux variables de type primitif, alors a==b est vrai si les deux variables ont la même valeur.
    • Il permet de vérifier l'identité des objets.
      Si a et b sont des objets, alors a==b est vrai uniquement si les deux variables pointent sur le même objet en mémoire.


    L'autoboxing n'est pour rien dans cela, et on peut retrouver la même problématique sans autoboxing :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    		Integer a = new Integer(0);
    		Integer b = a;
    		Integer c = new Integer(0);
     
    		System.out.println( (a==b) + " / " + a.equals(b));  // true / true
    		System.out.println( (a==c) + " / " + a.equals(c));  // false / true
    Il n'y a rien de faux là dedans.
    La notion d'identité est plus stricte que la notion d'égalité, et elle est trop importante pour qu'on l'ignore ! Il n'est pas faut d'utiliser l'opérateur == sur des objets !
    Cela n'a juste pas la même signification (égalité sur des types primitifs, et identité sur les objets).

    Alors oui il aurait été préférable d'avoir deux opérateurs distincts. Par exemple que == soit mappé sur equals() pour les objets, et qu'on puisse vérifier l'identité via un hypothétique === (qui ne pourrait pas être utilisé sur les primitifs).

    Et il est désormais impossible de modifier cela sans casser tous les codes existants !!!

    Note : pour la petite histoire l'opérateur == a quand même un sens, puisque l'opérateur d'identité sur des objets consistes ni plus ni moins qu'à vérifier l'égalité des références...



    Bref : lorsqu'on travaille avec des objets, on doit utiliser equals() pour vérifier l'égalité.


    a++


    @Levaillant : je ne vois pas trop l'intérêt d'utiliser les types wrapper à la place des primitifs. Au contraire il est bien plus simple d'utiliser directement les primitifs !

  9. #9
    Membre expert

    Homme Profil pro
    Consultant informatique
    Inscrit en
    Janvier 2004
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 301
    Points : 3 675
    Points
    3 675
    Par défaut
    La règle est simple:
    - soit tu type en primitif et utilise ==
    - soit tu type en objet et utilise equals (aucune exception, si object, equals est vraiment à préférer. Même si ça peut fonctionner quand même avec == c'est une très mauvaise idée, et tu dépends de mécanismes variables en fonction de la version de Java ie. les cache de bytes sont pas forcément implémenté en JRE 1.4, etc.)

    La version object à l'avantage non-négligeable de permettre d'utiliser "null" comme valeur pour exprimer "non initialisé, non applicable ou autre truc du genre". Les primitifs ont comme valeur par défaut 0, qui peut facilement être confondu avec un résultat de calcul réel.

    Sinon, pour lever des warnings à tout va, le top c'est: http://www.sonarsource.com (préparez-vous à apprendre un tas de trucs que vous n'imaginiez même pas)
    "Le plug gros problème des citations trouvées sur internet, c'est qu'on ne peut jamais garantir leur authenticité"

    Confucius, 448 av. J-C

  10. #10
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Février 2007
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 41
    Points : 25
    Points
    25
    Par défaut
    Bonjour,
    Pill_s a mis le doigt sur la raison qui m'avait incité à utiliser exclusivement des wrappers, le "null".
    Travaillant beaucoup sur diverses bases de données, il m'avait semblé opportun de les utiliser.
    Vos deux avis semblent confirmer ma première pensée donc, à savoir l'utilisation des wrappers n'est à privilégier que dans des cas où une variable peut-être null, et puis c'est tout !
    Merci à tous

  11. #11
    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
    Enfin depuis Java 1.8 j'aime pas trop compter sur "null" moi. Je préfère un bon OptionalInt... Bon, c'est un objet aussi, bien sûr.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  12. #12
    Membre expert

    Homme Profil pro
    Consultant informatique
    Inscrit en
    Janvier 2004
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 301
    Points : 3 675
    Points
    3 675
    Par défaut
    Ok je connaissais pas, mais en même temps, j'ai pas encore accès à Java 8 pour le dév...

    Sinon, ça étend pas Number? Ni Comparable? Ni rien du tout? Pourquoi ils ont fait cette classe du coup? Un OptionalObject générique aurait sûrement fais le même boulot...

    EDIT: ha zut ça existe en fait... https://docs.oracle.com/javase/8/doc.../Optional.html... bon bin aucune idée du pourquoi de l'optionalint
    "Le plug gros problème des citations trouvées sur internet, c'est qu'on ne peut jamais garantir leur authenticité"

    Confucius, 448 av. J-C

  13. #13
    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
    Citation Envoyé par Pill_S Voir le message
    EDIT: ha zut ça existe en fait... https://docs.oracle.com/javase/8/doc.../Optional.html... bon bin aucune idée du pourquoi de l'optionalint
    Toujours la même chose : les primitifs sont si atypique qu'il faut adapter le code si on ne veut pas passer par les types wrapper et l'autoboxing.
    On a donc grosso-modo :
    • Optional<T> pour les objets.
    • OptionalInt, OptionalDouble et OptionalLong pour les types primitifs correspondant.


    Malheureusement l'API de Java est assez pollué par cela...


    a++

  14. #14
    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 Pill_S Voir le message
    bon bin aucune idée du pourquoi de l'optionalint
    Je partais du principe que ça évite d'avoir deux objets quand un seul suffit pour un besoin simple, et que get().intValue() est moins pratique que getAsInt() pour comparer avec autre int.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

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

Discussions similaires

  1. Afficher une alerte en fonction d'une valeur
    Par guigui1976 dans le forum Excel
    Réponses: 3
    Dernier message: 13/10/2009, 20h49
  2. Afficher une ligne en cas de resultat nul
    Par JonathanP dans le forum Requêtes et SQL.
    Réponses: 9
    Dernier message: 28/08/2007, 11h41
  3. si checkbox cochée afficher une alerte lors du clic sur OK
    Par Nemesys dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 06/04/2007, 14h10
  4. Réponses: 1
    Dernier message: 21/02/2007, 18h17
  5. [Reports 6i] Faire afficher une alerte.
    Par macben dans le forum Reports
    Réponses: 3
    Dernier message: 15/02/2005, 10h47

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