548 votes

String.equals versus ==

Ce code sépare une chaîne de caractères en jetons et les stocke dans un tableau de chaînes de caractères, puis compare une variable avec la première maison ... pourquoi cela ne fonctionne-t-il pas ?

public static void main(String...aArguments) throws IOException {

    String usuario = "Jorman";
    String password = "14988611";

    String strDatos = "Jorman 14988611";
    StringTokenizer tokens = new StringTokenizer(strDatos, " ");
    int nDatos = tokens.countTokens();
    String[] datos = new String[nDatos];
    int i = 0;

    while (tokens.hasMoreTokens()) {
        String str = tokens.nextToken();
        datos[i] = str;
        i++;
    }

    //System.out.println (usuario);

    if ((datos[0] == usuario)) {
        System.out.println("WORKING");
    }
}

1 votes

Jetez un coup d'œil à ceci thejavageek.com/2013/07/27/

3 votes

"Changez datos[0] == usuario en datos[0].equals(usuario) pour obtenir la réponse correcte.

2 votes

Je vois que vous avez modifié votre réponse acceptée - je vous invite à lire mes commentaires à ce sujet et à reconsidérer votre décision. L'"histoire" de la réponse maintenant acceptée peut sembler bonne au départ, mais, à mon avis, elle ne résiste pas à un examen approfondi.

579voto

Alnitak Points 143355

Utilisez le string.equals(Object other) pour comparer des chaînes de caractères, et non la fonction == opérateur.

La fonction vérifie le contenu réel de la chaîne de caractères, l'élément == L'opérateur vérifie si les références aux objets sont égales. Notez que les constantes de type chaîne de caractères sont généralement "internées", de sorte que deux constantes ayant la même valeur peuvent être comparées avec l'opérateur == mais il est préférable de ne pas s'y fier.

if (usuario.equals(datos[0])) {
    ...
}

NB : la comparaison est faite sur 'usuario' parce qu'il est garanti non-nul dans votre code, bien que vous devriez quand même vérifier que vous avez effectivement des jetons dans le fichier datos sinon vous obtiendrez une exception de type "array-out-of-bounds".

10 votes

@mo : Ce n'est pas traité de manière égale, comme vous pouvez le voir dans cet exemple.

56 votes

@mo dans certains cas, même en java == peut être trompeur. Java met en cache les chaînes de caractères et donc quelque chose comme ceci retournerait vrai. String a = "Hello"; String b = "Hello"; a == b is true même si l'on s'attend normalement à ce que le résultat soit faux.

6 votes

@JonTaylor Votre exemple n'a rien à voir avec la mise en cache. Taper "Hello" dans du code java crée en fait un objet statique anonyme de type String dans la classe. Si vous utilisez un bon compilateur, les multiples occurrences de "Hello" pourrait utilisent le même objet statique String, mais il serait tout aussi valable de remplacer "Hello" par new String(new char[] {'H', 'e', ...})

557voto

Jops Points 6734

Rencontrez Jorman

Jorman est un homme d'affaires prospère et possède deux maisons.

enter image description here

Mais les autres ne le savent pas.

C'est le même Jorman ?

Lorsque vous demandez aux voisins des rues Madison ou Burke, c'est la seule chose qu'ils peuvent dire :

enter image description here

En utilisant la résidence seule, il est difficile de confirmer que c'est le même Jorman. Comme il s'agit de deux adresses différentes, il est naturel de supposer qu'il s'agit de deux personnes différentes.

C'est ainsi que l'opérateur == se comporte. Ainsi, il sera dit que datos[0]==usuario est fausse, car elle ne fait que compare les adresses .

Un enquêteur à la rescousse

Et si on envoyait un enquêteur ? Nous savons que c'est le même Jorman, mais nous devons le prouver. Notre détective examinera de près tous les aspects physiques. Avec une enquête approfondie, l'agent sera en mesure de conclure s'il s'agit de la même personne ou non. Voyons cela en termes de Java.

Voici le code source de String. equals() méthode :

enter image description here

Il compare les cordes caractère par caractère, afin d'arriver à la conclusion qu'elles sont effectivement égales.

C'est ainsi que la chaîne equals se comporte. Así que datos[0].equals(usuario) retournera vrai, car il effectue un comparaison logique .

19 votes

J'adore les exemples intuitifs et celui-ci est l'un des meilleurs que j'aie jamais vus. Les programmeurs novices peuvent facilement comprendre ce qui se passe dans les coulisses en le lisant.

12 votes

En fait, je pense que cette réponse est vraiment déroutant parce qu'il confond la personnalité de la personne nom avec le personne elle-même . Il confond également "égalité" et "équivalence". Le site this == anObject Le contrôle est sémantiquement exactement un test permettant de vérifier que l'on compare les deux mêmes objets (égalité), qui par définition doivent donc être équivalents. La finale return true après le while la boucle fait no signifie que nous avons le même "Jorman", cela signifie que les deux entités partagent la même valeur (équivalent), ce qui n'est pas le cas. no impliquent l'égalité. (La méthode Java .equals est mal nommée à cet égard).

1 votes

Cette réponse s'adresse aux débutants. La réponse suivante, celle de Michal Bernhard, fournit une analyse correcte du comportement incohérent de == dans Java lorsqu'il est appliqué à une chaîne.

96voto

Michal Bernhard Points 2203

C'est bien de remarquer que dans certains cas, l'utilisation de l'opérateur "==" peut conduire au résultat attendu, en raison de la façon dont Java traite les chaînes de caractères. - Les littéraux de chaîne sont internés (voir String.intern() ) pendant la compilation - ainsi, lorsque vous écrivez par exemple "hello world" dans deux classes et que vous comparez ces chaînes de caractères avec "==", vous pourriez obtenir le résultat suivant : true, ce qui est attendu en vertu de l'article 2.1.1.1. spécification ; lorsque vous comparez les mêmes chaînes de caractères (si elles ont la même valeur), lorsque la première est une chaîne littérale (c'est-à-dire définie par l'intermédiaire de la commande "i am string literal" ) et le second est construit pendant l'exécution, c'est-à-dire avec le mot clé "new" comme new String("i am string literal") le == (égalité) renvoie un résultat faux, car les deux sont des instances différentes de l'objet String classe.

La seule façon correcte est d'utiliser .equals() -> datos[0].equals(usuario) . == ne dit que si deux objets sont la même instance d'objet (c'est-à-dire ont la même adresse mémoire).

Mise à jour : 01.04.2013 J'ai mis à jour ce post en raison des commentaires ci-dessous qui sont en quelque sorte justes. A l'origine, je déclarais que l'internage (String.intern) est un effet secondaire de l'optimisation de la JVM. Bien qu'il permette certainement d'économiser des ressources mémoire (ce que j'entendais par "optimisation"), il s'agit principalement d'une caractéristique du langage.

6 votes

En fait, ce n'est pas seulement un effet secondaire de l'optimisation jvm et n'a rien à voir avec le compilateur du tout. L'identité des chaînes statiques (littéraux) dans toutes les classes est garantie conformément à la spécification Java VM et fonctionne avec toutes les VM qui sont au moins compatibles avec Java 1.1.

7 votes

Si vous voulez dire le chapitre 2.3 de la spécification JVM "Les littéraux de chaîne et, plus généralement, les chaînes qui sont les valeurs d'expressions constantes sont "internées" de manière à partager des instances uniques, en utilisant la méthode String.intern". Eh bien, c'est garanti par jvm (selon la spécification), mais pour moi, cela signifie toujours l'optimisation. Il n'y a aucune valeur sémantique de ceci AFAIK. D'un autre côté, == a une sémantique d'"égalité d'identité" et la méthode equals() a une "égalité d'objet", donc vous devriez obéir à cela et ne pas compter sur la spécification jvm, qui est un "guide" pour les implémentateurs jvm plutôt que pour les développeurs (ils ont la spécification du langage Java).

3 votes

Les littéraux, les noms de classe et autres sont internés pour se conformer à la spécification, ce n'est pas une simple optimisation. "xxx" est toujours == "xxx", cela fait partie de la conception du langage et non d'un détail/guide impl.

36voto

hari Points 342

equals() est une méthode de Object qui doit être surchargée par le programmeur. String la surcharge pour vérifier si deux chaînes de caractères sont égales, c'est-à-dire en termes de contenu et non de référence.

== vérifie si les références des deux objets sont les mêmes.

Examinez les programmes

String abc = "Awesome" ;
String xyz =  abc;

if(abc == xyz)
     System.out.println("Refers to same string");

Ici, le abc y xyz les deux se réfèrent au même String "Awesome" . D'où l'expression (abc == xyz) es true .

String abc = "Hello World";
String xyz = "Hello World";

if(abc == xyz)
    System.out.println("Refers to same string");
else
    System.out.println("Refers to different strings");

if(abc.equals(xyz))
     System.out.prinln("Contents of both strings are same");
else
     System.out.prinln("Contents of strings are different");

Aquí abc y xyz sont deux chaînes de caractères différentes avec le même contenu "Hello World" . D'où ici l'expression (abc == xyz) es false où comme (abc.equals(xyz)) es true .

J'espère que vous avez compris la différence entre == y <Object>.equals()

Gracias.

0 votes

Je me demande dans quel cas (non évident) abc == xyz fonctionnera-t-il ?

7 votes

Le code sort (après avoir corrigé prinln en println) : Se réfère à la même chaîne, le contenu des deux chaînes est le même, c'est-à-dire qu'ici, (abc == xyz) et (abc.equals(xyz)) sont tous deux vrais !

6 votes

Comme indiqué ci-dessus, cette réponse est fausse. en raison des mécanismes d'optimisation interne, il arrive que deux objets chaîne de caractères ayant le même contenu soient en fait représentés par un seul objet. cette optimisation est possible parce que les chaînes de caractères sont immuables.

26voto

Bhushan Bhangale Points 6284

Au lieu de

datos[0] == usuario

utiliser

datos[0].equals(usuario)

== compare la référence de la variable où .equals() compare les valeurs, ce qui est ce que vous voulez.

11 votes

Assurez-vous que le côté gauche n'est pas nul.

0 votes

Ou utiliser usario.equals à la place, comme le démontre la réponse sélectionnée par @Alnitak. Cela vous permet de gagner une étape (ou tout un tas) si vous savez initialement que usario n'est pas nul.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X