Je sais que ==
a quelques problèmes lorsque l'on compare deux Strings
. Il semble que String.equals()
soit une meilleure approche. Eh bien, je fais des tests avec JUnit et j’ai tendance à utiliser assertEquals(str1, str2)
. Est-ce un moyen fiable d'affirmer que deux chaînes contiennent le même contenu? J'utiliserais assertTrue(str1.equals(str2))
, mais vous n'aurez alors pas l'avantage de voir quelles sont les valeurs attendues et réelles en cas d'échec.
Sur une note connexe, quelqu'un at-il un lien vers une page ou un fil de discussion expliquant clairement les problèmes rencontrés avec str1 == str2
?
Vous devriez toujours utiliser .equals()
lorsque vous comparez Strings
en Java.
JUnit appelle la méthode .equals()
pour déterminer l'égalité dans la méthode assertEquals(Object o1, Object o2)
.
Vous êtes donc en sécurité avec assertEquals(string1, string2)
. (Parce que String
s sont Object
s)
Voici un lien vers une grande question de Stackoverflow concernant certaines des différences entre ==
et .equals()
.
assertEquals
utilise la méthode equals
à des fins de comparaison. Il existe une assertion différente, assertSame
, qui utilise l'opérateur ==
.
Pour comprendre pourquoi ==
ne devrait pas être utilisé avec des chaînes, vous devez comprendre ce que fait ==
: il effectue un contrôle d'identité. C'est-à-dire que a == b
vérifie si a
et b
se rapportent à même objet. Il est intégré au langage et son comportement ne peut pas être modifié par différentes classes. La méthode equals
, en revanche, peut être remplacée par des classes. Bien que son comportement par défaut (dans la classe Object
) consiste à effectuer une vérification d’identité à l’aide de l’opérateur ==
, de nombreuses classes, y compris String
, la remplacent pour effectuer une vérification "d’équivalence". Dans le cas de String
, au lieu de vérifier si a
et b
se rapportent au même objet, a.equals(b)
vérifie si les objets auxquels ils font référence sont des chaînes contenant exactement les mêmes personnages.
Temps d’analogie: imaginez que chaque objet String
soit un morceau de papier avec quelque chose d’écrit. Disons que j'ai deux feuilles de papier sur lesquelles est écrit "Foo" et une autre sur laquelle est écrit "Bar". Si je prends les deux premiers morceaux de papier et que j'utilise ==
pour les comparer, cela retournera false
car il est essentiellement question de "S'agit-il du même morceau de papier?". Il n'est même pas nécessaire de regarder ce qui est écrit sur le papier. Le fait que je lui donne deux bouts de papier (plutôt que le même deux fois) signifie qu'il retournera false
. Si j'utilise equals
, cependant, la méthode equals
lira les deux bouts de papier et veillera à ce qu'ils disent la même chose ("Foo"), et ainsi ils retourneront true
.
Le problème avec les chaînes est que le Java a le concept "d'interner" des chaînes, ce qui est (automatiquement) automatiquement effectué sur les littéraux de chaîne de votre code. Cela signifie que si vous avez deux littéraux de chaîne équivalents dans votre code (même s'ils appartiennent à des classes différentes), ils feront tous deux référence au même objet String
. Cela fait que l'opérateur ==
renvoie true
plus souvent que l'on pourrait s'y attendre.
En un mot, vous pouvez avoir deux objets String contenant les mêmes caractères, mais différents objets (dans des emplacements de mémoire différents). L'opérateur == vérifie que deux références pointent sur le même objet (emplacement mémoire), mais la méthode equals () vérifie si les caractères sont identiques.
Généralement, vous souhaitez vérifier si deux chaînes contiennent les mêmes caractères, et non si elles pointent vers le même emplacement de mémoire.
Oui, il est utilisé tout le temps pour les tests. Il est très probable que la structure de test utilise .equals () pour de telles comparaisons.
Ci-dessous un lien expliquant "l'erreur d'égalité de chaîne". Pour l'essentiel, les chaînes dans Java sont des objets, et lorsque vous comparez l'égalité d'objet, elles sont généralement comparées en fonction de l'adresse de la mémoire et non du contenu. De ce fait, deux chaînes n'occuperont pas la même adresse, même si leur contenu est identique, de sorte qu'elles ne correspondent pas correctement, même si elles se ressemblent une fois imprimées.
http://blog.enrii.com/2006/03/15/Java-string-equality-common-mistake/
public class StringEqualityTest extends TestCase {
public void testEquality() throws Exception {
String a = "abcde";
String b = new String(a);
assertTrue(a.equals(b));
assertFalse(a == b);
assertEquals(a, b);
}
}
Le JUnit assertEquals(obj1, obj2)
appelle effectivement obj1.equals(obj2)
.
Il y a aussi assertSame(obj1, obj2)
qui fait obj1 == obj2
(c’est-à-dire qu'il vérifie que obj1
et obj2
font référence à l’instance identique). en essayant d'éviter.
Donc ça va.
"L'opérateur
==
vérifie si deuxObjects
sont exactement les mêmesObject
."
http://leepoint.net/notes-Java/data/strings/12stringcomparison.html
String
est un Object
en Java, il entre donc dans cette catégorie de règles de comparaison.