Question Comment comparer les chaînes en Java?


J'ai utilisé le == opérateur dans mon programme pour comparer toutes mes chaînes jusqu'à présent. Cependant, j'ai rencontré un bug, changé l'un d'eux en .equals() à la place, et cela a corrigé le bug.

Est == mal? Quand devrait-il et ne devrait-il pas être utilisé? Quelle est la différence?


727


origine


Réponses:


== tests pour l'égalité de référence (s'il s'agit du même objet).

.equals() tests pour l'égalité des valeurs (si elles sont logiquement "égales").

Objects.equals () vérifie pour null avant d'appeler .equals() donc vous n'avez pas à (disponible à partir de JDK7, également disponible en Goyave).

String.contentEquals () compare le contenu de la String avec le contenu de tout CharSequence (disponible depuis Java 1.5).

Par conséquent, si vous voulez tester si deux chaînes ont la même valeur, vous voudrez probablement utiliser Objects.equals().

// 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 

// ... string literals are concatenated by the compiler
// and the results are interned.
"test" == "te" + "st" // --> true

// ... but you should really just call Objects.equals()
Objects.equals("test", new String("test")) // --> true
Objects.equals(null, "test") // --> false
Objects.equals(null, null) // --> true

Vous presque toujours vouloir utiliserObjects.equals(). dans le rare situation où vous connaître vous avez affaire à interné cordes, vous pouvez utilisation ==.

De JLS 3.10.5. Littéraux de chaîne:

De plus, une chaîne de caractères se réfère toujours à même instance de classe String. C'est parce que les chaînes littérales - ou, plus généralement, les chaînes qui sont les valeurs des expressions constantes (§15.28) - sont "internés" afin de partager des instances uniques, en utilisant la méthode String.intern.

Des exemples similaires peuvent également être trouvés dans JLS 3.10.5-1.


4949



== teste les références d'objet, .equals() teste les valeurs de chaîne.

Parfois, il semble que == compare les valeurs, parce que Java fait des trucs en coulisse pour s'assurer que les mêmes chaînes en ligne sont en fait le même objet.

Par exemple:

String fooString1 = new String("foo");
String fooString2 = new String("foo");

// Evaluates to false
fooString1 == fooString2;

// Evaluates to true
fooString1.equals(fooString2);

// Evaluates to true, because Java uses the same object
"bar" == "bar";

Mais méfiez-vous des nulls! 

== poignées null cordes bien, mais en appelant .equals() à partir d'une chaîne nulle provoquera une exception:

String nullString1 = null;
String nullString2 = null;

// Evaluates to true
System.out.print(nullString1 == nullString2);

// Throws a NullPointerException
System.out.print(nullString1.equals(nullString2));

Donc, si vous le savez fooString1 peut être nul, dire au lecteur qu'en écrivant

System.out.print(fooString1 != null && fooString1.equals("bar"));

Ce qui suit est plus court, mais il est moins évident qu'il vérifie null (à partir de Java 7):

System.out.print(Objects.equals(fooString1, "bar"));

627



== compare les références d'objet.

.equals() compare les valeurs de chaîne.

parfois == donne des illusions de comparer des valeurs de chaîne, comme dans les cas suivants:

String a="Test";
String b="Test";
if(a==b) ===> true

Cela est dû au fait que lorsque vous créez un littéral chaîne, la machine virtuelle Java recherche d'abord ce littéral dans le pool de chaînes et, s'il trouve une correspondance, la même référence sera donnée à la nouvelle chaîne. Pour cette raison, nous obtenons:

(a == b) ===> vrai

                       String Pool
     b -----------------> "test" <-----------------a

cependant, == échoue dans le cas suivant:

String a="test";
String b=new String("test");
if (a==b) ===> false

Dans ce cas pour new String("test") l'instruction new String sera créée sur le tas, et cette référence sera donnée à b, alors b sera donné une référence sur le tas, pas dans le pool String.

À présent a pointe vers une chaîne dans le pool String tout en b pointe vers une chaîne sur le tas. Pour cette raison, nous obtenons:

if (a == b) ===> faux.

                String Pool
     "test" <-------------------- a

                   Heap
     "test" <-------------------- b

Tandis que .equals() compare toujours une valeur de String afin de donner true dans les deux cas:

String a="Test";
String b="Test";
if(a.equals(b)) ===> true

String a="test";
String b=new String("test");
if(a.equals(b)) ===> true

Donc en utilisant .equals() c'est toujours mieux.


396



le == L'opérateur vérifie si les deux chaînes sont exactement le même objet.

le .equals() méthode vérifiera si les deux chaînes ont la même valeur.


203



Les chaînes de Java sont immuables. Cela signifie que chaque fois que vous essayez de modifier / modifier la chaîne, vous obtenez une nouvelle instance. Vous ne pouvez pas changer la chaîne d'origine. Cela a été fait pour que ces instances de chaîne puissent être mises en cache. Un programme typique contient beaucoup de références de chaînes et la mise en cache de ces instances peut réduire l'empreinte mémoire et augmenter les performances du programme.

Lorsque vous utilisez l'opérateur == pour la comparaison de chaînes, vous ne comparez pas le contenu de la chaîne, mais comparez réellement l'adresse mémoire. Si elles sont toutes les deux égales, cela retournera vrai et faux sinon. Considérant que les chaînes égales en chaîne compare le contenu de la chaîne.

Donc, la question est de savoir si toutes les chaînes sont mises en cache dans le système, comment se fait-il == renvoie false alors que les égales sont vraies? Eh bien, c'est possible. Si vous faites une nouvelle chaîne comme String str = new String("Testing") vous finissez par créer une nouvelle chaîne dans le cache même si le cache contient déjà une chaîne ayant le même contenu. En bref "MyString" == new String("MyString") retournera toujours faux.

Java parle aussi de la fonction intern () qui peut être utilisée sur une chaîne pour l'intégrer au cache "MyString" == new String("MyString").intern() reviendra vrai.

Remarque: L'opérateur == est beaucoup plus rapide qu'égal juste parce que vous comparez deux adresses de mémoire, mais vous devez être sûr que le code ne crée pas de nouvelles instances de chaîne dans le code. Sinon, vous rencontrerez des bugs.


154



String a = new String("foo");
String b = new String("foo");
System.out.println(a == b); // prints false
System.out.println(a.equals(b)); // prints true

Assurez-vous de comprendre pourquoi. C'est parce que le == la comparaison compare seulement les références; la equals() méthode effectue une comparaison caractère par caractère du contenu.

Lorsque vous appelez nouveau pour a et b, chacun obtient une nouvelle référence qui pointe vers le "foo" dans la table de chaînes. Les références sont différentes, mais le contenu est le même.


132



Oui, c'est mauvais ...

== signifie que vos deux références de chaîne sont exactement le même objet. Vous avez peut-être entendu que c'est le cas parce que Java garde une sorte de table littérale (ce qu'il fait), mais ce n'est pas toujours le cas. Certaines chaînes sont chargées différemment, construites à partir d'autres chaînes, etc. Vous ne devez donc jamais supposer que deux chaînes identiques sont stockées au même endroit.

Equals fait la comparaison réelle pour vous.


114



Oui, == est mauvais pour comparer des chaînes (n'importe quels objets vraiment, à moins que vous sachiez qu'ils sont canoniques). == compare simplement les références d'objets. .equals() tests d'égalité. Pour les cordes, elles seront souvent les mêmes mais comme vous l'avez découvert, ce n'est pas toujours garanti.


110