208 votes

La méthode assertEquals de Java est-elle fiable ?

Je sais que == a quelques problèmes lors de la comparaison de deux Strings . Il semble que String.equals() est une meilleure approche. Eh bien, je fais des tests JUnit et mon penchant est d'utiliser assertEquals(str1, str2) . Est-ce un moyen fiable d'affirmer que deux chaînes de caractères contiennent le même contenu ? J'utiliserais assertTrue(str1.equals(str2)) mais vous n'avez pas l'avantage de voir quelles sont les valeurs attendues et réelles en cas d'échec.

Dans un autre ordre d'idées, quelqu'un a-t-il un lien vers une page ou un fil de discussion qui explique clairement les problèmes liés à l'utilisation de l'Internet ? str1 == str2 ?

1 votes

Si vous n'êtes pas sûr, vous pouvez lire le code, ou le Javadoc. BTW si vous voulez tester qu'il s'agit du même objet, vous pouvez utiliser assertSame.

2 votes

Si str1 et str2 sont nuls, assertEquals() est vrai, mais assertTrue(str1.equals(str2)) lève une exception. Le premier exemple imprime également un message d'erreur utile comme le contenu de str1 et str2, le second ne le fait pas.

286voto

jjnguy Points 62123

Vous devez toujours utiliser .equals() en comparant Strings en Java.

JUnit appelle le .equals() pour déterminer l'égalité dans la méthode assertEquals(Object o1, Object o2) .

Vous pouvez donc utiliser en toute sécurité assertEquals(string1, string2) . (Parce que String sont Object s)

Voici un lien vers une excellente question sur Stackoverflow concernant certaines des différences entre == y .equals() .

13 votes

IIRC assertEquals() réussit si les deux chaînes de caractères sont nulles. Si ce n'est pas ce que vous voulez, appelez aussi assertNotNull().

11 votes

De plus, si vous voulez tester pour ==, vous pouvez appeler assertSame()

9 votes

Je ne dirais pas toujours ; parfois, l'égalité des références est souhaitée, même pour les chaînes de caractères.

32voto

Laurence Gonsalves Points 50783

assertEquals utilise le equals pour la comparaison. Il existe une affirmation différente, assertSame qui utilise le == opérateur.

Pour comprendre pourquoi == ne doit pas être utilisé avec des chaînes de caractères, vous devez comprendre ce que les == fait : il effectue un contrôle d'identité. C'est-à-dire, a == b vérifie si a y b se référer à la même objet . Il est intégré au langage, et son comportement ne peut pas être modifié par des classes différentes. Le site equals d'autre part, peut être remplacée par des classes. Alors que son comportement par défaut (dans la méthode Object ) est d'effectuer un contrôle d'identité en utilisant la classe == opérateur, de nombreuses classes, dont String pour effectuer une vérification d'"équivalence". Dans le cas de String au lieu de vérifier si a y b font référence au même objet, a.equals(b) vérifie si les objets auxquels ils font référence sont tous deux des chaînes de caractères contenant exactement les mêmes caractères.

Analogie : imaginez que chaque String L'objet est un morceau de papier avec quelque chose d'écrit dessus. Disons que j'ai deux morceaux de papier avec "Foo" écrit dessus, et un autre avec "Bar" écrit dessus. Si je prends les deux premiers morceaux de papier et que je me sers de == pour les comparer, il retournera false parce qu'il demande essentiellement "est-ce que c'est le même morceau de papier ?". Il n'a même pas besoin de regarder 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 Toutefois, le equals va lire les deux morceaux de papier et voir qu'ils disent la même chose ("Foo"), et donc elle retournera true .

Ce qui peut prêter à confusion avec les chaînes de caractères, c'est que Java a un concept d'"internage" des chaînes de caractères, et cela est (effectivement) automatiquement effectué sur tous les littéraux de chaîne de caractères dans votre code. Cela signifie que si vous avez deux chaînes de caractères équivalentes dans votre code (même si elles sont dans des classes différentes), elles feront toutes deux référence à la même chaîne de caractères String objet. Cela rend le == retour de l'opérateur true plus souvent que l'on pourrait s'y attendre.

0 votes

"C'est-à-dire que a == b vérifie si a et b sont le même objet." Techniquement, il vérifie si a et b RENVOI au même objet, puisque a et b sont des références. A moins que je ne me trompe fortement.

0 votes

@user1903064 c'est correct. Puisque les variables non primitives ne peuvent contenir que des références en Java, il est courant de sauter le niveau supplémentaire d'indirection lorsqu'on en parle, mais je suis d'accord que dans ce cas, être plus explicite est bénéfique. J'ai mis à jour la réponse. Merci pour la suggestion !

8voto

Ken Liu Points 7779

En bref, vous pouvez avoir deux objets String qui contiennent les mêmes caractères mais qui sont des objets différents (dans des emplacements 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 que les caractères sont identiques.

En général, vous souhaitez vérifier si deux chaînes de caractères contiennent les mêmes caractères, et non si elles pointent vers le même emplacement mémoire.

5voto

Carl Manaster Points 23696
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);
    }
}

3voto

Soviut Points 26384

Oui, il est utilisé en permanence pour les tests. Il est très probable que le cadre de test utilise .equals() pour des comparaisons de ce type.

Vous trouverez ci-dessous un lien expliquant "l'erreur d'égalité des chaînes de caractères". Essentiellement, les chaînes de caractères en Java sont des objets, et lorsque vous comparez l'égalité des objets, ils sont généralement comparés en fonction de l'adresse mémoire, et non du contenu. Pour cette raison, deux chaînes de caractères n'occuperont pas la même adresse, même si leur contenu est identique, et ne correspondront donc pas correctement, même si elles ont la même apparence à l'impression.

http://blog.enrii.com/2006/03/15/java-string-equality-common-mistake/

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