web-dev-qa-db-fra.com

String.equals versus ==

Ce code sépare une chaîne en jetons et les stocke dans un tableau de chaînes, puis compare une variable à la première maison ... pourquoi 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");
    }
}
512
franvergara66

Utilisez la fonction string.equals(Object other) pour comparer des chaînes, et non l'opérateur ==.

La fonction vérifie le contenu réel de la chaîne, l'opérateur == vérifie si les références aux objets sont égales. Notez que les constantes de chaîne sont généralement "internées", de sorte que deux constantes avec la même valeur peuvent en réalité être comparées avec ==, mais il est préférable de ne pas compter sur cela.

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

NB: la comparaison est faite sur 'usuario' car c'est garanti non-nul dans votre code, bien que vous deviez quand même vérifier que vous avez bien quelques jetons dans le tableau datos sinon vous aurez un tableau exception-of-bounds.

550
Alnitak

Rencontrez Jorman

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

enter image description here

Mais d'autres ne le savent pas.

Est-ce le même Jorman?

Lorsque vous interrogez des 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 comme ça que l’opérateur == se comporte. On dira donc que datos[0]==usuario est faux, car il ne fait que comparer 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 déterminer s'il s'agit de la même personne ou non. Voyons que cela se passe en Java termes.

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

enter image description here

Il compare le caractère de Strings par caractère, afin de conclure à leur égalité.

C'est comme ça que la méthode String equals se comporte. Donc datos[0].equals(usuario) retournera true, car elle effectuera une comparaison logique .

519
Jops

Il est bon de noter que dans certains cas, l'utilisation de l'opérateur "==" peut conduire au résultat attendu, car la manière dont Java traite les chaînes - littéraux de chaîne sont internés (voir String.intern()) lors de la compilation - ainsi, lorsque vous écrivez par exemple "hello world" dans deux classes et comparez ces chaînes avec "==", vous pouvez obtenir le résultat: true, ce qui est attendu selon spécification ; lorsque vous comparez les mêmes chaînes (si elles ont la même valeur) lorsque la première est littérale (c'est-à-dire définie via "i am string literal") et que la seconde est construite au moment de l'exécution, c'est-à-dire. Avec le mot-clé "new" tel que new String("i am string literal"), l'opérateur == (égalité) renvoie false, car ils sont tous deux des instances différentes de la classe String.

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

Mise à jour : 01.04.2013 J'ai mis à jour ce message en raison de commentaires ci-dessous qui sont en quelque sorte corrects. A l'origine, j'avais déclaré que interning (String.intern) était un effet secondaire de l'optimisation de la machine virtuelle Java. Bien que cela économise certainement des ressources de mémoire (ce que je voulais dire par "optimisation"), il est principalement caractéristique du langage

93
Michal Bernhard

La fonction equals() est une méthode de la classe Object qui doit être remplacée par le programmeur. String class la remplace pour vérifier si deux chaînes sont égales, c'est-à-dire contenu et non référencé.

== l'opérateur vérifie si les références des deux objets sont identiques.

Considérez les programmes

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

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

Ici, abc et xyz désignent tous deux le même String"Awesome". Par conséquent, l'expression (abc == xyz) est 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");

Ici abc et xyz sont deux chaînes différentes ayant le même contenu "Hello World". D'où ici l'expression (abc == xyz) est false où en tant que (abc.equals(xyz)) est true.

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

Merci.

33
HariShankar

Au lieu de

datos[0] == usuario

utilisation

datos[0].equals(usuario)

== compare la référence de la variable où .equals() compare les valeurs souhaitées.

26
Bhushan Bhangale

== teste l'égalité de référence.

.equals() teste l'égalité des valeurs.

Par conséquent, si vous voulez réellement vérifier si deux chaînes ont la même valeur, vous devez utiliser .equals() (sauf dans quelques cas où vous pouvez garantir que deux chaînes ayant la même valeur seront représentées par le même objet, par exemple: String interning).

== sert à vérifier si deux chaînes sont identiques Object.

// These two have the same value
new String("test").equals("test") ==> true 

// ... but they are not the same object
new String("test") == "test" ==> false 

// ... neither are these
new String("test") == new String("test") ==> false 

// ... but these are because literals are interned by 
// the compiler and thus refer to the same object
"test" == "test" ==> true 

// concatenation of string literals happens at compile time resulting in same objects
"test" == "te" + "st"  ==> true

// but .substring() is invoked at runtime, generating distinct objects
"test" == "!test".substring(1) ==> false

Il est important de noter que == est beaucoup moins cher que equals() (une comparaison de pointeur unique au lieu d'une boucle). Par conséquent, dans les cas où cela est applicable (vous pouvez donc garantir que vous ne traitez chaînes internes) peut présenter une amélioration importante de la performance. Cependant, ces situations sont rares.

23
Puneet Purohit
The == operator checks if the two references point to the same object or not.
.equals() checks for the actual string content (value).

Notez que la méthode .equals () appartient à la classe Object (super classe de toutes les classes). Vous devez le remplacer conformément aux exigences de votre classe, mais pour String, il est déjà implémenté et il vérifie si deux chaînes ont la même valeur ou non.

Case1)
String s1 = "Stack Overflow";
String s2 = "Stack Overflow";
s1 == s1;      // true
s1.equals(s2); // true
Reason: String literals created without null are stored in the string pool in the permgen area of the heap. So both s1 and s2 point to the same object in the pool.
Case2)
String s1 = new String("Stack Overflow");
String s2 = new String("Stack Overflow");
s1 == s2;      // false
s1.equals(s2); // true
Reason: If you create a String object using the `new` keyword a separate space is allocated to it on the heap.
18
Aniket Thakur

Cela fonctionnera également si vous appelez intern() sur la chaîne avant de l'insérer dans le tableau. Les chaînes internées sont égales en référence (==) si et seulement si elles sont égales en valeur (equals().)

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.intern();            
    i++;
}

//System.out.println (usuario);

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

Analysons le Java suivant, pour comprendre l'identité et l'égalité des chaînes:

public static void testEquality(){
    String str1 = "Hello world.";
    String str2 = "Hello world.";

    if (str1 == str2)
        System.out.print("str1 == str2\n");
    else
        System.out.print("str1 != str2\n");

    if(str1.equals(str2))
        System.out.print("str1 equals to str2\n");
    else
        System.out.print("str1 doesn't equal to str2\n");

    String str3 = new String("Hello world.");
    String str4 = new String("Hello world.");

    if (str3 == str4)
        System.out.print("str3 == str4\n");
    else
        System.out.print("str3 != str4\n");

    if(str3.equals(str4))
        System.out.print("str3 equals to str4\n");
    else
        System.out.print("str3 doesn't equal to str4\n");
}

Lorsque la première ligne du code String str1 = "Hello world." est exécutée, une chaîne \Hello world." est créée et la variable str1 s'y réfère. Une autre chaîne "Hello world." ne sera pas créée à nouveau lorsque la ligne de code suivante sera exécutée pour des raisons d'optimisation. La variable str2 fait également référence au ""Hello world." existant.

L'opérateur == vérifie l'identité de deux objets (si deux variables se rapportent au même objet). Puisque str1 et str2 font référence à la même chaîne en mémoire, elles sont identiques. La méthode equals vérifie l'égalité de deux objets (si deux objets ont le même contenu). Bien entendu, le contenu de str1 et str2 est identique.

Lorsque le code String str3 = new String("Hello world.") s'exécute, une nouvelle instance de chaîne avec un contenu "Hello world." est créée et elle est désignée par la variable str3. Et puis une autre instance de chaîne avec le contenu "Hello world." est créée à nouveau et désignée par str4. Puisque str3 et str4 font référence à deux instances différentes, elles ne sont pas identiques, mais leur contenu est identique.

Par conséquent, la sortie contient quatre lignes:

Str1 == str2

Str1 equals str2

Str3! = str4

Str3 equals str4
11
Harry He

Vous devez utiliser chaîne égale pour comparer deux chaînes pour l’égalité, et non opérateur == qui compare simplement les références.

9
Michael Klement

== l'opérateur compare la référence d'un objet en Java. Vous pouvez utiliser la méthode equals de string.

String s = "Test";
if(s.equals("Test"))
{
    System.out.println("Equal");
}
7
Himanshu Mohta

L'opérateur == est une simple comparaison de valeurs.
Pour les références d'objet, les (valeurs) sont les (références). Donc x == y retourne vrai si x et y font référence au même objet.

6
engy

@ Melkhiah66 Vous pouvez utiliser la méthode equals au lieu de la méthode '==' pour vérifier l'égalité. Si vous utilisez intern (), il vérifie si l'objet est dans le pool s'il est présent, puis renvoie égal sinon, différent. La méthode equals utilise en interne hashcode et vous permet d'obtenir le résultat souhaité.

public class Demo
{
  public static void main(String[] args)
  {
              String str1 = "Jorman 14988611";
    String str2 = new StringBuffer("Jorman").append(" 14988611").toString();
    String str3 = str2.intern();
    System.out.println("str1 == str2 " + (str1 == str2));           //gives false
    System.out.println("str1 == str3 " + (str1 == str3));           //gives true
    System.out.println("str1 equals str2 " + (str1.equals(str2)));  //gives true
    System.out.println("str1 equals str3 " + (str1.equals(str3)));  //gives true
  }
}
 </ code>
6
tinker_fairy

Si vous comparez une valeur affectée de la chaîne, c'est-à-dire une chaîne primitive, "==" et .equals fonctionneront, mais pour le nouvel objet chaîne, vous ne devez utiliser que .equals, et ici "==" ne fonctionnera pas.

Exemple:

String a = "name";

String b = "name";

if(a == b) et (a.equals(b)) retournent la valeur true.

Mais

String a = new String("a");

Dans ce cas, if(a == b) retournera false

Il est donc préférable d'utiliser l'opérateur .equals ...

6
mreaevnia

Généralement, .equals est utilisé pour la comparaison Object, où vous souhaitez vérifier si deux Objects ont une valeur identique.

== pour la comparaison de référence (les deux Objects sont les mêmes Object sur le tas) & pour vérifier si le Object est nul. Il est également utilisé pour comparer les valeurs des types primitifs.

6
Abhinav Jayaram

Je sais que c’est une vieille question, mais voici comment je la vois (je trouve très utile):


Explications techniques

En Java, toutes les variables sont soit types primitifs ou références.

(Si vous avez besoin de savoir ce qu'est une référence: "Les variables d'objet" ne sont que des pointeurs sur des objets. Donc, avec Object something = ..., quelque chose est vraiment une adresse en mémoire (un nombre).)

== compare les valeurs exactes. Donc, il compare si les valeurs primitives sont les mêmes, ou si les références (adresses) sont les mêmes. C'est pourquoi == ne fonctionne souvent pas sur les chaînes; Les chaînes sont des objets et faire == sur deux variables de chaîne ne fait que comparer si l'adresse est la même en mémoire, comme d'autres l'ont souligné. .equals() appelle la méthode de comparaison des objets, qui comparera les objets réels pointés par les références. Dans le cas des chaînes, il compare chaque caractère pour voir si elles sont égales.


La partie intéressante:

Alors pourquoi == retourne-t-il parfois true pour Strings? Notez que les chaînes sont immuables. Dans votre code, si vous le faites

String foo = "hi";
String bar = "hi";

Comme les chaînes sont immuables (lorsque vous appelez .trim() ou quelque chose, cela produit une nouvelle chaîne, sans modifier l'objet d'origine pointé en mémoire), vous n'avez pas vraiment besoin de deux objets String("hi") différents. Si le compilateur est intelligent, le bytecode lira pour ne générer qu'un seul objet String("hi"). Donc si tu le fais

if (foo == bar) ...

juste après, ils pointent sur le même objet et retournent true. Mais vous avez rarement l'intention de le faire. Au lieu de cela, vous demandez à l'utilisateur d'entrer, ce qui crée de nouvelles chaînes de caractères dans différentes parties de la mémoire, etc., etc.

Note: Si vous faites quelque chose comme baz = new String(bar) le compilateur peut toujours comprendre que c'est la même chose. Mais le point principal est que lorsque le compilateur voit des chaînes littérales, il peut facilement optimiser les mêmes chaînes.

Je ne sais pas comment cela fonctionne au moment de l'exécution, mais je suppose que la JVM ne conserve pas de liste de "chaînes en direct" et vérifie si une même chaîne existe. (Par exemple, si vous lisez une ligne d'entrée deux fois et que l'utilisateur entre la même entrée deux fois, il ne vérifiera pas si la deuxième chaîne d'entrée est identique à la première et les dirigera vers la même mémoire). Cela permettrait d'économiser un peu de mémoire, mais c'est tellement négligeable que les frais généraux n'en valent pas la peine. Encore une fois, il est facile pour le compilateur d’optimiser des chaînes littérales.

Voilà, vous avez une explication sérieuse pour == vs. .equals() et pourquoi cela semble aléatoire.

6
Raekye

a==b

Compare les références, pas les valeurs. L'utilisation de == avec des références d'objet est généralement limitée aux éléments suivants:

  1. Comparer pour voir si une référence est null.

  2. Comparer deux valeurs enum. Cela fonctionne car il n'y a qu'un seul objet pour chaque constante enum.

  3. Vous voulez savoir si deux références se rapportent au même objet

"a".equals("b")

Compare les valeurs pour l'égalité. Comme cette méthode est définie dans la classe Object, à partir de laquelle toutes les autres classes sont dérivées, elle est automatiquement définie pour chaque classe. Cependant, il n'effectue pas de comparaison intelligente pour la plupart des classes à moins que la classe ne la remplace. Il a été défini de manière significative pour la plupart des Java classes de base. S'il n'est pas défini pour une classe (utilisateur), il se comporte de la même façon que ==.

4
rohan kamat

La .equals() vérifie si les deux chaînes ont la même valeur et renvoie la valeur boolean où l'opérateur == vérifie si les deux chaînes sont le même objet.

4
Dinoop Nair

Quelqu'un a dit sur un post plus haut que == est utilisé pour int et pour vérifier les NULL. Il peut également être utilisé pour vérifier les opérations booléennes et les types de caractères.

Soyez très prudent et vérifiez bien que vous utilisez un caractère et non une chaîne. par exemple

    String strType = "a";
    char charType = 'a';

pour les chaînes, vous devriez alors cocher la case Cela serait correct

    if(strType.equals("a")
        do something

mais

    if(charType.equals('a')
        do something else

serait incorrect, vous devrez faire ce qui suit

    if(charType == 'a')
         do something else
4
Keith Spriggs

Utilisez Split plutôt que tokenizer, il fournira sûrement une sortie exacte pour E.g:

string name="Harry";
string salary="25000";
string namsal="Harry 25000";
string[] s=namsal.split(" ");
for(int i=0;i<s.length;i++)
{
System.out.println(s[i]);
}
if(s[0].equals("Harry"))
{
System.out.println("Task Complete");
}

Après cela, je suis sûr que vous obtiendrez de meilleurs résultats .....

3
Harrydev