Java: les assertEquals(String, String) sont-ils fiables?
je sais que ==
a quelques problèmes lorsque l'on compare les deux Strings
. Il semble que String.equals()
soit une meilleure approche. Eh bien, je fais des tests JUnit et mon penchant est d'utiliser assertEquals(str1, str2)
. Est-ce une façon fiable d'affirmer que deux chaînes contiennent le même contenu? Je voudrais utiliser assertTrue(str1.equals(str2))
, mais alors vous ne recevez pas l'avantage de voir ce que les valeurs attendues et réelles sont sur l'échec.
Sur une note connexe, quelqu'un aurait-il un lien vers une page ou un fil qui explique clairement les problèmes avec str1 == str2
?
7 réponses
Vous devriez toujours utiliser .equals()
lorsque l'on compare Strings
en Java.
JUnit appelle la méthode .equals()
pour déterminer l'égalité dans la méthode assertEquals(Object o1, Object o2)
.
donc, vous êtes certainement en sécurité en utilisant assertEquals(string1, string2)
. (Parce que String
s sont Object
s)
voici un lien vers une grande question de débordement des piles concernant certaines des différences entre ==
et .equals()
.
assertEquals
utilise la méthode equals
pour la comparaison. Il existe une autre assertion, 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 fait un contrôle d'identité. C'est-à-dire a == b
vérifie si a
et b
se réfèrent au même objet . Il est construit dans la langue, et son comportement ne peut pas être modifié par des classes différentes. Par contre, la méthode equals
peut être remplacée par des classes. Alors que son comportement par défaut (dans la classe Object
) est de faire un contrôle d'identité à l'aide de l'opérateur ==
, de nombreuses classes, y compris String
, l'outrepassent pour faire à la place un contrôle "d'équivalence". Dans le cas de String
, au lieu de vérifier si a
et b
font référence au même objet, a.equals(b)
vérifie si les objets auxquels ils se réfèrent sont les deux chaînes qui contiennent exactement les mêmes caractères.
temps D'analogie: imaginez que chaque objet String
est un morceau de papier avec quelque chose écrit dessus. Disons que j'ai deux morceaux de papier avec "Toto" écrit sur eux, et un autre avec "Bar". Si je prends les deux premiers morceaux de papier et utilise ==
pour les comparer il retournera false
parce que c'est essentiellement Demander "sont-ce la même pièce de papier?". Il n'a même pas à chercher à ce qui est écrit sur le papier. Le fait que je lui donne deux morceaux 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 morceaux de papier et verra qu'ils disent la même chose ("Foo"), et donc il retournera true
.
le truc qui prête à confusion avec les chaînes, C'est que le Java a un concept de chaînes "internes", et ceci est (effectivement) exécuté automatiquement sur n'importe quelle chaîne littérale de votre code. Cela signifie que si vous avez deux chaînes de caractères littérales équivalentes dans votre code (même si elles sont dans des classes différentes), elles se référeront en fait toutes les deux au même objet String
. Cela fait que l'opérateur ==
retourne true
plus souvent que l'on pourrait s'y attendre.
en bref - vous pouvez avoir deux objets String qui contiennent les mêmes caractères mais sont des objets différents (dans des emplacements de mémoire différents). L'opérateur = = vérifie que deux références pointent vers le même objet (Emplacement mémoire), mais la méthode equals() vérifie si les caractères sont les mêmes.
habituellement, vous êtes intéressé à vérifier si deux chaînes contiennent les mêmes caractères, pas s'ils pointent vers le même emplacement de mémoire.
Oui, c'est utilisé tout le temps pour les tests. Il est très probable que le cadre d'essai soit utilisé .equals() pour les comparaisons de ce genre.
ci-dessous est un lien expliquant la"chaîne de caractères égalité erreur". Essentiellement, les chaînes de caractères en Java sont des objets, et lorsque vous comparez l'égalité des objets, elles sont généralement comparées en fonction de l'adresse mémoire, et non du contenu. Pour cette raison, deux chaînes n'occuperont pas la même adresse, même si leur contenu est identique, donc elles n'occuperont pas correspondent correctement, même si elles sont identiques lorsqu'elles sont 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)
ne s'appelle en effet obj1.equals(obj2)
.
il y a aussi assertSame(obj1, obj2)
qui fait obj1 == obj2
(i.e., vérifie que obj1
et obj2
font référence à même instance), ce qui est ce que vous essayez d'éviter.
donc tu vas bien.
"
==
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, de sorte qu'il tombe dans la catégorie de règles de comparaison.