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 ?

179
demandé sur Philip Kirkbride 2009-07-29 21:47:34

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() .

249
répondu jjnguy 2017-05-23 11:54:59

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.

28
répondu Laurence Gonsalves 2015-06-04 02:01:22

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.

6
répondu Ken Liu 2009-07-29 18:15:06

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 /

3
répondu Soviut 2009-07-29 17:48:48
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);
    }
}
3
répondu Carl Manaster 2009-07-29 17:54:28

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.

3
répondu Jack Leow 2009-07-29 18:06:12

" == opérateur vérifie si deux Objects sont exactement les mêmes Object ."

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.

1
répondu Zachery Delafosse 2010-01-20 19:44:02