Pourquoi la comparaison de valeur de chaîne d'opérateur == n'est-elle pas passée à Java?

50

Tout programmeur Java compétent sait que vous devez utiliser String.equals () pour comparer une chaîne, plutôt que == car == vérifie l’égalité des références.

Lorsque je traite avec des chaînes, je vérifie la plupart du temps l’égalité des valeurs plutôt que l’égalité des références. Il me semble que ce serait plus intuitif si le langage permettait la comparaison des valeurs de chaîne en utilisant simplement ==.

À titre de comparaison, l' opérateur == de C # vérifie l'égalité des valeurs pour la chaîne s. Et si vous avez réellement besoin de vérifier l’égalité des références, vous pouvez utiliser String.ReferenceEquals.

Un autre point important est que les chaînes sont immuables, il n'y a donc aucun mal à autoriser cette fonctionnalité.

Y a-t-il une raison particulière pour laquelle cela n'est pas implémenté en Java?

l46kok
la source
12
Vous voudrez peut-être examiner Scala, où ==se trouvent l' égalité d'objet et l' eqégalité de référence ( ofps.oreilly.com/titles/9780596155957/… ).
Giorgio
En guise de remarque, cela ne vous aidera peut-être pas, mais pour autant que je sache, vous pouvez comparer des littéraux de chaîne avec un '=='
Kgrover
10
@Kgrover: vous le pouvez, mais ce n'est qu'un sous-produit commode de l'égalité des références et de la façon dont Java optimise de manière agressive les littéraux de correspondance de chaînes en références au même objet. En d'autres termes, cela fonctionne, mais pour les mauvaises raisons.
tdammers
1
@aviv, l' ==opérateur ne correspond qu'à Equalssi l' ==opérateur a été implémenté de cette façon. Le comportement par défaut de ==est le même que ReferenceEquals(en fait, ReferenceEqualsest défini comme la version de l'objet de ==)
Patrick Huizinga
3
C'est une conséquence des décisions de conception qui ont beaucoup de sens dans de nombreux autres scénarios. Mais puisque vous semblez le savoir et que vous le demandez de toute façon, je me sens obligé de répondre à votre question: pourquoi faut-il un cas d'utilisation pour la comparaison de références de chaînes?
Jacob Raihle

Réponses:

90

Je suppose que ce n'est que cohérence, ou "principe du moindre étonnement". String est un objet, il serait donc surprenant que cet objet soit traité différemment des autres objets.

À l'époque de la sortie de Java (~ 1995), le simple Stringluxe était un luxe absolu pour la plupart des programmeurs habitués à représenter des chaînes comme des tableaux à terminaison nulle. StringLe comportement est maintenant ce qu'il était à l'époque, et c'est bien; changer subtilement le comportement par la suite pourrait avoir des effets surprenants et indésirables sur les programmes de travail.

En guise de remarque, vous pouvez utiliser String.intern()une représentation canonique (internée) de la chaîne, après laquelle des comparaisons peuvent être effectuées ==. L'internat prend du temps, mais après cela, les comparaisons seront très rapides.

Ajout: contrairement à ce que suggèrent certaines réponses, il ne s'agit pas de supporter la surcharge des opérateurs . L' +opérateur (concaténation) fonctionne sur Strings même si Java ne prend pas en charge la surcharge d'opérateur; c'est simplement traité comme un cas spécial dans le compilateur, résolvant en StringBuilder.append(). De même, ==aurait pu être traité comme un cas spécial.

Alors pourquoi étonner avec cas particulier +mais pas avec ==? Parce que, +tout simplement, ne compile pas lorsqu'il est appliqué à des non- Stringobjets, c'est donc rapidement apparent. Le comportement différent de ==serait beaucoup moins apparent et donc beaucoup plus étonnant quand il vous frappera.

Joonas Pulakka
la source
8
Les cas spéciaux ajoutent l'étonnement.
Blrfl
17
Les cordes étaient un luxe en 1995? Vraiment?? Regardez l'histoire des langages informatiques. Le nombre de langues qui comportaient un type de chaîne à l'époque dépassait de loin le nombre de celles qui n'en possédaient pas. Combien de langues en plus de C et de ses descendants utilisaient des tableaux à zéro terminal?
WarrenT
14
@WarrenT: Bien sûr, certaines langues (sinon la plupart) avaient un type de chaîne, mais les chaînes compatibles Unicode, les ordures ramassées étaient une nouveauté en 1995, je pense. Par exemple, Python a introduit les chaînes Unicode avec la version 2.0, année 2000. Le choix de l’immuabilité était également un choix controversé à cette époque.
Joonas Pulakka
3
@JoonasPulakka Ensuite, vous devriez peut-être modifier votre réponse pour le dire. Parce qu’en l’état actuel, la partie «luxe total» de votre réponse est tout à fait fausse.
svick
1
L'internat a un coût: vous obtenez une chaîne qui ne sera jamais désallouée. (Eh bien, pas si vous utilisez votre propre moteur d'interning que vous pouvez jeter.)
Donal Fellows
32

James Gosling , le créateur de Java, l’a expliqué en juillet 2000 :

J'ai laissé de côté la surcharge d'opérateur comme un choix assez personnel car j'avais vu trop de gens en abuser en C ++. Au cours des cinq à six dernières années, j'ai passé beaucoup de temps à interroger les personnes sur la surcharge des opérateurs. C’est vraiment fascinant, car la communauté est divisée en trois parties: environ 20 à 30% de la population pense que la surcharge des opérateurs est enfant du diable; Quelqu'un a fait quelque chose avec la surcharge d'opérateur qui les a vraiment cochés, parce qu'ils ont utilisé like pour l'insertion de liste et que cela rend la vie vraiment, vraiment déroutante. Une bonne partie de ce problème provient du fait qu’il n’ya qu’une demi-douzaine d’opérateurs que vous pouvez raisonnablement surcharger, et pourtant il existe des milliers ou des millions d’opérateurs que les gens aimeraient définir - vous devez donc choisir,

Ross Patterson
la source
50
Ah, oui, le vieil outil "émoussons l'outil pointu pour que les employés ne se fassent pas du mal".
Blrfl
22
@Blrfl: Si un outil crée plus de problèmes qu'il n'en résout, ce n'est pas un bon outil. Bien entendu, décider si tel est le cas en cas de surcharge des opérateurs risque de donner lieu à une très longue discussion.
Giorgio
15
-1. Cela ne répond pas du tout à la question. Java est surchargé par les opérateurs. L' ==opérateur est surchargé pour les objets et les primitives. L' +opérateur est surchargé pour byte, short, int, long, float, double, Stringet probablement quelques autres j'ai oublié. Il aurait été parfaitement possible de surcharge ==pour Stringaussi bien.
Jörg W Mittag Le
10
@ Jorg - non, ce n'est pas le cas. La surcharge d'opérateur est impossible à définir au niveau de l'utilisateur. Il y a bien quelques cas particuliers dans le compilateur mais ça ne se qualifie guère
AZ01
9
@Blrfl: Cela ne me dérange pas que les fous se blessent. C'est quand ils sortent accidentellement de mon œil que je m'énerve.
Jonas
9

Cohérence dans la langue. Avoir un opérateur qui agit différemment peut être surprenant pour le programmeur. Java n'autorise pas les utilisateurs à surcharger les opérateurs - par conséquent, l'égalité de référence est la seule signification raisonnable ==entre les objets.

Dans Java:

  • Entre les types numériques, ==compare l'égalité numérique
  • Entre types booléens, ==compare l'égalité booléenne
  • Entre les objets, ==compare l'identité de référence
    • Utiliser .equals(Object o)pour comparer les valeurs

C'est ça. Règle simple et simple pour identifier ce que vous voulez. Tout cela est traité dans la section 15.21 du JLS . Il comprend trois sous-sections faciles à comprendre, à mettre en œuvre et à raisonner.

Une fois que vous autorisez la surcharge de== , le comportement exact n'est pas quelque chose que vous pouvez regarder vers le JLS et mettre le doigt sur un élément spécifique et dire "c'est comme ça que ça marche", le code peut devenir difficile à raisonner. Le comportement exact de ==peut être surprenant pour un utilisateur. Chaque fois que vous le voyez, vous devez revenir en arrière et vérifier ce que cela signifie réellement.

Comme Java ne permet pas de surcharger les opérateurs, il est nécessaire de disposer d’un test d’égalité des valeurs que vous pouvez remplacer par la définition de base. Ainsi, il a été mandaté par ces choix de conception. ==en Java, teste numeric pour les types numériques, égalité booléenne pour les types booléens et égalité de référence pour tout le reste (ce qui peut se substituer .equals(Object o)à tout ce qu'ils veulent pour l'égalité des valeurs).

Ce n’est pas une question de "existe-t-il un cas d’utilisation pour une conséquence particulière de cette décision de conception" mais plutôt "il s’agit d’une décision de conception visant à faciliter ces autres choses, c’est une conséquence de celle-ci".

String interning en est un exemple. Selon JLS 3.10.5 , tous les littéraux de chaîne sont internés. Les autres chaînes sont internées si on y invoque .intern(). Cela "foo" == "foo"est vrai, est une conséquence des décisions de conception prises pour minimiser l’empreinte mémoire des littéraux de chaîne. Au-delà, l’internalisation des chaînes est quelque chose qui, au niveau de la JVM, a un peu de visibilité sur l’utilisateur, mais dans la très grande majorité des cas, ne devrait pas concerner le programmeur (et les cas d’utilisation pour quelque chose qui figurait en haut de la liste pour les concepteurs lorsqu’on envisage cette fonctionnalité).

Les gens vont le souligner +et +=sont surchargés pour String. Cependant, ce n'est ni ici ni là-bas. Cela reste le cas que si ==a une signification d'égalité de valeur pour String (et uniquement String), il faudrait une méthode différente (qui n'existe que dans String) pour l'égalité de référence. De plus, cela compliquerait inutilement les méthodes qui prennent Object et s’attendent ==à ce qu’elles se comportent d’une manière et .equals()d’une autre, obligeant les utilisateurs à casse toutes ces méthodes pour String.

Le contrat cohérent pour ==on Objects est qu'il ne s'agit que d'égalité de référence et qu'il .equals(Object o)existe pour tous les objets qui doivent tester l'égalité de valeur. Compliquer cela complique beaucoup trop de choses.


la source
Merci d'avoir pris le temps de répondre. Ce serait une excellente réponse aux autres questions que j'ai liées. Malheureusement, cela ne convient pas à cette question. Je mettrai à jour le PO avec des clarifications basées sur les commentaires. Je recherche davantage les cas d'utilisation où un utilisateur d'une langue voudrait avoir les faux négatifs lors de la comparaison de chaînes. Le langage fournit cette fonctionnalité par souci de cohérence, je voudrais maintenant que nous allions un peu plus loin. Peut-être y pensons-nous du concepteur du nouveau langage, est-ce nécessaire? (malheureusement, pas de lang-design.SE)
Anonsage
3
@Anonsage ce n'est pas un faux négatif. Ils ne sont pas le même objet. C'est tout ce que ça dit. Je dois également souligner que, dans Java 8, cela new String("foo") == new String("foo")peut être vrai (voir Déduplication des chaînes ).
1
En ce qui concerne la conception de la langue, CS.SE annonce qu’elle peut être sur le sujet.
ooh, merci! J'y posterai mes futures questions de lang-design. :) Et oui, malheureusement, "faux négatif" n'est pas la manière la plus précise de décrire ma question et ce que je recherche. J'ai besoin d'écrire plus de mots pour que les gens n'aient pas à deviner ce que je suis Essayant de dire.
Anonsage
2
"La cohérence dans le langage" aide également avec les génériques
Brendan
2

Java ne prend pas en charge la surcharge des opérateurs, ce qui signifie ==que cela ne s'applique qu'aux types primitifs ou aux références. Tout le reste nécessite l'invocation d'une méthode. Pourquoi les concepteurs ont-ils répondu à cette question? Si je devais deviner, c'est probablement parce que la surcharge des opérateurs ajoute une complexité qu'ils n'étaient pas intéressés à ajouter.

Je ne suis pas un expert en C #, mais les concepteurs de ce langage semblent l'avoir mis en place de telle sorte que chaque primitive soit un structet chaque structest un objet. Etant donné que C # permet la surcharge des opérateurs, cette configuration permet à toute classe, et pas seulement String, de se faire travailler de la manière "attendue" avec n'importe quel opérateur. C ++ permet la même chose.

Blrfl
la source
1
« Java ne surcharge d'opérateur prend pas en charge, ce qui moyen == applique uniquement aux types primitifs ou références Toute autre exige l' invocation d'une méthode. ».: On pourrait ajouter que si ==signifiait l' égalité des cordes, il nous faudrait une autre notation pour l' égalité de référence.
Giorgio
@ George: Exactement. Voir mon commentaire sur la réponse de Gilad Naaman.
Blrfl
Bien que cela puisse être résolu par une méthode statique qui compare les références de deux objets (ou d'un opérateur). Comme en C #, par exemple.
Gilad Naaman le
@GiladNaaman: Ce serait un jeu à somme nulle car cela pose le problème opposé à celui de Java: l'égalité serait sur un opérateur et vous auriez à invoquer une méthode pour comparer les références. De plus, vous devrez imposer à toutes les classes l'obligation d'implémenter quelque chose qui puisse être lié ==. Cela ajoute effectivement une surcharge d'opérateur, ce qui aurait des implications énormes sur la manière dont Java est implémenté.
Blrfl
1
@Blrfl: Pas vraiment. Il y aura toujours un moyen défini de comparer reference ( ClassName.ReferenceEquals(a,b)), ainsi qu'un ==opérateur et une Equalsméthode par défaut pointant tous les deux ReferenceEquals.
Gilad Naaman le
2

Cela a été fait différemment dans d'autres langues.

En Object Pascal (Delphi / Free Pascal) et C #, l'opérateur d'égalité est défini pour comparer des valeurs, et non des références, lors de l'utilisation de chaînes.

Particulièrement en Pascal, string est un type primitif (une des choses que j'aime beaucoup à propos de Pascal, obtenir NullreferenceException simplement à cause d'une chaîne non initialisée est tout simplement irritant) et avoir une sémantique de copie sur écriture rendant ainsi (la plupart du temps) très pas cher (en d’autres termes, n’est visible que lorsque vous commencez à concaténer des chaînes de plusieurs mégaoctets).

C'est donc une décision de conception de langage pour Java. Lorsqu'ils ont conçu le langage, ils ont suivi la méthode C ++ (comme Std :: String) pour que les chaînes soient des objets. IMHO est un hack permettant de compenser l'absence d'un type de chaîne réel dans C, au lieu de faire des chaînes une primitive (ce qu'elles sont).

Pour une raison donc, je ne peux que spéculer sur le fait qu’ils ont simplifié les choses au lieu de coder l’opérateur, ce qui a créé une exception pour les chaînes du compilateur.

Fabricio Araujo
la source
Comment cela répond-il à la question posée?
moucher le
Voir la dernière phrase (que j'ai séparée dans un paragraphe approprié dans une édition).
Fabricio Araujo
1
IMHO, Stringaurait dû être un type primitif en Java. Contrairement aux autres types, le compilateur doit connaître String; de plus, les opérations sur ce sujet seront suffisamment courantes pour que, pour de nombreux types d’applications, elles puissent constituer un goulot d’étranglement en termes de performances (qui pourrait être atténué par le support natif). Un objet string[en minuscule] typique aurait un objet alloué sur le tas pour contenir son contenu, mais aucune référence "normale" à cet objet n'existerait nulle part; il pourrait donc s'agir d'un simple indirect Char[]ou Byte[]plutôt que d'avoir à être Char[]indirect par le biais d'un autre objet.
Supercat
1

En Java, il n’ya aucune surcharge d’opérateur, c’est pourquoi les opérateurs de comparaison ne sont surchargés que pour les types primitifs.

La classe 'String' n'est pas une primitive. Par conséquent, elle ne surcharge pas '==' et utilise par défaut la comparaison de l'adresse de l'objet dans la mémoire de l'ordinateur.

Je ne suis pas sûr, mais je pense que dans Java 7 ou 8 Oracle a fait une exception dans le compilateur de reconnaître str1 == str2commestr1.equals(str2)

Gilad Naaman
la source
"Je ne suis pas sûr, mais je pense que dans Java 7 ou 8, Oracle a fait une exception dans le compilateur pour reconnaître str1 == str2 en tant que str1.equals (str2)": je ne serais pas surpris: Oracle semble être moins préoccupé avec le minimalisme que Sun était.
Giorgio
2
Si true, c'est un très mauvais bidouillage car cela signifie qu'il y a maintenant une classe que le langage traite différemment de toutes les autres et rompt le code qui compare les références. : - @
Blrfl
1
@ WillihamTotland: Prenons le cas contraire. Actuellement, si je crée deux chaînes s1et s2leur donne le même contenu, elles transmettent la s1.equals(s2)comparaison d' égalité ( ) mais pas la comparaison de même référence ( ==) car il s'agit de deux objets différents. Changer la sémantique de l' ==égalité signifie faire s1 == s2évaluer trueoù elle évaluait false.
Blrfl
2
@Brlfl: Bien que cela soit vrai, cela semble être une très mauvaise chose sur laquelle compter, car les chaînes sont des objets immuables et internables.
Williham Totland le
2
@Giorgio: "Java 7 ou 8 oracle a fait une exception dans le compilateur pour reconnaître str1 == str2 comme str1.equals (str2)" Nope, la spécification du langage Java indique: Opérateurs d'égalité de référence : "Si les opérandes d'un opérateur d'égalité sont à la fois du type référence ou du type null, l'opération est une égalité d'objet. " C'est tous les gens. Je n'ai rien trouvé de nouveau à ce sujet dans la version préliminaire de Java 8 non plus.
David Tonhofer
0

Java semble avoir été conçu pour respecter une règle fondamentale selon laquelle l' ==opérateur doit être légal chaque fois qu'un opérateur peut être converti en un type, et doit comparer le résultat de cette conversion avec l'opérande non converti.

Cette règle n’est pas propre à Java, mais elle a des effets de grande portée (et à mon humble avis malheureux) sur la conception d’autres aspects du langage liés au type. Il aurait été plus propre de préciser les comportements de ==ce qui concerne les combinaisons particulières de types d'opérandes, et interdire les combinaisons de types X et Y où x1==y1et x2==y1n'impliqueraient x1==x2, mais les langues font rarement que [dans cette philosophie, double1 == long1devrait soit indiquer si double1n’est pas une représentation exacte de long1, ou refuse de compiler;int1==Integer1devrait être interdit, mais il devrait exister un moyen pratique et efficace de déterminer si un objet est un entier en boîte avec une valeur particulière (la comparaison avec quelque chose qui n'est pas un entier en boîte devrait simplement renvoyer false)].

En ce qui concerne l'application de l' ==opérateur aux chaînes, si Java avait interdit les comparaisons directes entre des opérandes de type Stringet de Object, il aurait pu éviter les surprises dans le comportement de ==, mais il n'y a aucun comportement qu'il puisse implémenter pour de telles comparaisons qui ne serait pas étonnant. Avoir deux références de chaîne conservées dans le type Objectse comporte différemment des références conservées dans le type Stringaurait été beaucoup moins surprenant que le fait d'avoir l'un ou l'autre de ces comportements diffère de celui d'une comparaison légale de type mixte. Si cela String1==Object1est légal, cela impliquerait que la seule façon pour que les comportements String1==String2et les comportements Object1==Object2correspondent String1==Object1soit pour qu’ils se correspondent.

supercat
la source
Je dois manquer quelque chose, mais IMHO ==sur des objets devrait simplement appeler (Null-safe) des égaux et quelque chose d'autre (par exemple, ===ou System.identityEqual) devrait être utilisé pour la comparaison d'identité. Le mélange des primitives et des objets serait initialement interdit (il n'y avait pas d'autoboxing avant la version 1.5), puis une règle simple pouvait être trouvée (par exemple, unbox null-safe, puis cast, puis compare).
Maaartinus
@maaartinus: Une bonne conception de langage devrait utiliser des opérateurs d'égalité distincts pour l'égalité des valeurs et des références. Bien que je convienne sur le plan conceptuel, il aurait été possible de int==Integerrenvoyer un opérateur falsesi le Integerest, et sinon de comparer des valeurs, mais cette approche aurait été différente de celle de ==toutes les autres circonstances, où elle contraint inconditionnellement les deux opérandes au même type avant. en les comparant. Personnellement, je me demande si l'auto-unboxing a été mis en place dans le but de permettre int==Integerà un comportement qui ne soit pas
insensé
... puisque la comparaison automatique des intréférences et la comparaison des références auraient été ridicules [mais n'auraient pas toujours échoué]. Sinon, je ne vois aucune raison d'autoriser une conversion implicite pouvant échouer avec un NPE.
Supercat
Je pense que mon idée est cohérente. N'oubliez pas que dans le monde meilleur, cela ==n'a rien à voir avec identityEquals. +++ "Opérateurs d'égalité séparés pour l'égalité de valeur et de référence" - mais lesquels? Je considère à la fois primitive ==et equalsque faire la valeur de comparaison dans le sens où les equalsregards à la valeur de la référence. +++ Quand cela est ==voulu dire equals, alors int==IntegerDEVRAIT faire la sélection automatique et comparer les références en utilisant des équivalents null-safe. +++ J'ai bien peur que mon idée ne soit pas vraiment la mienne, mais ce que Kotlin fait.
Maaartinus
@maaartinus: si ==jamais l'égalité de référence n'a été testée, elle pourrait raisonnablement effectuer un test d'égalité de valeur null-safe. Le fait qu'il fait l' égalité de test de référence, cependant, limite sévèrement la façon dont il peut gérer des comparaisons référence / valeur mixtes sans contradiction. Notez également que Java est basé sur la notion que les opérateurs promeuvent les deux opérandes au même type, plutôt que de générer des comportements spéciaux basés sur les combinaisons de types impliqués. Par exemple, 16777217==16777216.0fretourne trueparce qu'il effectue une conversion avec perte du premier opérande en float...
Supercat
0

En général, il y a de très bonnes raisons de vouloir pouvoir tester si deux références d'objet pointent sur le même objet. J'ai eu beaucoup de fois que j'ai écrit

Address oldAddress;
Address newAddress;
... populate values ...
if (oldAddress==newAddress)
... etc ...

Je peux ou non avoir une fonction d'égal à égal dans de tels cas. Si je le fais, la fonction equals peut comparer tout le contenu des deux objets. Souvent, il ne fait que comparer un identifiant. "A et B sont des références au même objet" et "A et B sont deux objets différents ayant le même contenu" sont bien entendu deux idées très différentes.

Il est probablement vrai que pour les objets immuables, tels que Strings, le problème est moins grave. Avec des objets immuables, nous avons tendance à penser que l’objet et la valeur sont la même chose. Eh bien, quand je dis "nous", je veux dire "je", au moins.

Integer three=new Integer(3);
Integer triangle=new Integer(3);
if (three==triangle) ...

Bien sûr, cela retourne faux, mais je peux voir quelqu'un penser que cela devrait être vrai.

Mais une fois que vous dites que == compare les poignées de référence et non le contenu des objets en général, il serait potentiellement déroutant de créer un cas particulier pour Strings. Comme quelqu'un d'autre l'a dit, si vous vouliez comparer les poignées de deux objets String? Y aurait-il une fonction spéciale pour le faire uniquement pour les chaînes?

Et à propos de ...

Object x=new String("foo");
Object y=new String("foo");
if (x==y) ...

Est-ce faux parce que ce sont deux objets différents, ou vrai parce que ce sont des chaînes dont le contenu est égal?

Alors oui, je comprends à quel point les programmeurs sont désorientés. Je l'ai fait moi-même, je veux dire écrire si myString == "foo" quand je voulais dire si myString.equals ("foo"). Mais à moins de redéfinir la signification de l'opérateur == pour tous les objets, je ne vois pas comment y répondre.

Geai
la source
Notez que d'autres langues modernes sur la machine virtuelle, telles que Scala, ==signifient "chaînes égales".
Andres F.
@AndresF. (haussement d'épaules) En Java, "<" signifie "inférieur à", alors qu'en XML, il "ouvre une balise". En VB, "=" peut signifier "est égal à", alors qu'en Java, il n'est utilisé que pour l'affectation. Etc. Il n’est pas surprenant que des langages différents utilisent des symboles différents pour signifier la même chose, ou un même symbole pour signifier différentes choses.
Jay
Ce n'était pas un creuser à votre réponse. C'était juste un commentaire. Je soulignais simplement qu’un langage plus moderne que Java avait saisi l’opportunité de redéfinir le sens de ==, comme vous l’aviez mentionné à la fin.
Andres F.
@AndresF. Et ma réponse n’a rien à dire avec votre commentaire, mais simplement que différentes langues abordent ces questions de différentes manières. :-) En fait, j'aime bien la façon dont VB gère cela ... pause pour les sifflements et les bêtises des haineux VB ... "=" compare toujours la valeur (pour les types définis par le système), qu'elle soit primitive ou objet. "Est" compare les poignées de deux objets. Cela me semble plus intuitif.
Jay
Sûr. Mais Scala est bien plus proche de Java que de Visual Basic. J'aime penser que les concepteurs de Scala ont compris que l'utilisation de Java ==était sujette aux erreurs.
Andres F.
0

Ceci est une question valable Strings, et non seulement pour les chaînes, mais aussi pour d' autres objets immuables représentant une « valeur », par exemple Double, BigIntegeret même InetAddress.

Pour rendre l' ==opérateur utilisable avec Strings et d'autres classes de valeur, je vois trois alternatives:

  • Demandez au compilateur de connaître toutes ces classes de valeurs et la façon de comparer leurs contenus. Si cela ne représentait qu'une poignée de classes du java.langpaquet, je le prendrais en considération, mais cela ne couvre pas les cas comme InetAddress.

  • Autoriser la surcharge de l'opérateur afin qu'une classe définisse son ==comportement de comparaison.

  • Supprimez les constructeurs publics et demandez aux méthodes statiques renvoyant des instances d'un pool, renvoyant toujours la même instance pour la même valeur. Pour éviter les fuites de mémoire, vous avez besoin de quelque chose comme SoftReferences dans le pool, qui n'existait pas dans Java 1.0. Et maintenant, pour maintenir la compatibilité, les String()constructeurs ne peuvent plus être supprimés.

La seule chose qui pourrait encore être faite aujourd'hui serait d'introduire la surcharge d'opérateurs, et personnellement, je ne voudrais pas que Java aille dans cette voie.

Pour moi, la lisibilité du code est primordiale, et un programmeur Java sait que les opérateurs ont une signification fixe, définie dans la spécification du langage, alors que les méthodes sont définies par un code et que leur signification doit être recherchée dans la Javadoc de la méthode. Je voudrais rester avec cette distinction même si cela signifie que les comparaisons de chaînes ne pourront pas utiliser l' ==opérateur.

Il n’ya qu’un aspect des comparaisons de Java qui me dérange: l’effet de la boxe automatique et de la box-boxing. Il cache la distinction entre le type primitif et le type wrapper. Mais quand vous les comparez avec ==, ils sont très différents.

    int i=123456;
    Integer j=123456;
    Integer k=123456;
    System.out.println(i==j);  // true or false? Do you know without reading the specs?
    System.out.println(j==k);  // true or false? Do you know without reading the specs?
Ralf Kleberhoff
la source