Java: ¿assertEquals (String, String) es fiable?


Sé que == tiene algunos problemas al comparar dos Strings. Parece que String.equals() es un mejor enfoque. Bueno, estoy haciendo pruebas JUnit y mi inclinación es usar assertEquals(str1, str2). ¿Es esta una forma confiable de afirmar que dos cadenas contienen el mismo contenido? Usaría assertTrue(str1.equals(str2)), pero entonces no obtienes el beneficio de ver cuáles son los valores esperados y reales en caso de falla.

En una nota relacionada, ¿alguien tiene un enlace a una página o hilo que explica claramente los problemas con str1 == str2?

Author: Philip Kirkbride, 2009-07-29

7 answers

Debe siempre usar .equals() al comparar Strings en Java.

JUnit llama al método .equals() para determinar la igualdad en el método assertEquals(Object o1, Object o2).

Entonces, definitivamente estás seguro usando assertEquals(string1, string2). (Porque Strings son Objects)

Aquí hay un enlace a una gran pregunta de Stackoverflow con respecto a algunas de las diferencias entre == y .equals().

 249
Author: jjnguy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:54:59

assertEquals utiliza el método equals para la comparación. Hay una afirmación diferente, assertSame, que utiliza el operador ==.

Para entender por qué == no debe usarse con cadenas, necesita entender lo que hace ==: hace una verificación de identidad. Es decir, a == b comprueba si a y bse refieren al mismo objeto. Está integrado en el lenguaje, y su comportamiento no puede ser cambiado por diferentes clases. El método equals, por otro lado, puede ser anulado por clases. Mientras que su comportamiento por defecto (en la clase Object) es hacer una comprobación de identidad usando el operador ==, muchas clases, incluyendo String, lo anulan para hacer una comprobación de "equivalencia". En el caso de String, en lugar de comprobar si a y b se refieren al mismo objeto, a.equals(b) comprueba si los objetos a los que se refieren son cadenas que contienen exactamente los mismos caracteres.

Tiempo de analogía: imagine que cada String objeto es un pedazo de papel con algo escrito en él. Vamos digamos que tengo dos pedazos de papel con "Foo" escrito en ellos, y otro con" Bar " escrito en él. Si tomo los dos primeros pedazos de papel y uso == para compararlos, regresará false porque esencialmente está preguntando "¿son estos el mismo pedazo de papel?". No necesita siquiera mirar lo que está escrito en el papel. El hecho de que le estoy dando dos pedazos de papel (en lugar de la misma dos veces) significa que volverá false. Sin embargo, si utilizo equals, el método equals leerá las dos partes de papel y ver que dicen la misma cosa ("Foo"), y así va a volver true.

El bit que se confunde con las Cadenas es que Java tiene un concepto de "internación" de cadenas, y esto se realiza (efectivamente) automáticamente en cualquier cadena literal en su código. Esto significa que si tiene dos literales de cadena equivalentes en su código (incluso si están en clases diferentes), ambos se referirán al mismo objeto String. Esto hace que el operador == devuelva true más a menudo de lo que uno podría esperar.

 28
Author: Laurence Gonsalves,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-04 02:01:22

En pocas palabras - puede tener dos objetos de cadena que contienen los mismos caracteres pero son objetos diferentes (en diferentes ubicaciones de memoria). El operador = = comprueba que dos referencias apunten al mismo objeto (ubicación de memoria), pero el método equals () comprueba si los caracteres son los mismos.

Normalmente le interesa comprobar si dos cadenas contienen los mismos caracteres, no si apuntan a la misma ubicación de memoria.

 6
Author: Ken Liu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-29 18:15:06

Sí, se utiliza todo el tiempo para las pruebas. Es muy probable que el marco de pruebas utiliza .equals () para comparaciones como estas.

A continuación hay un enlace que explica el "error de igualdad de cadena". Esencialmente, las cadenas en Java son objetos, y cuando se compara la igualdad de objetos, normalmente se comparan en función de la dirección de memoria, y no por el contenido. Debido a esto, dos cadenas no ocuparán la misma dirección, incluso si su contenido es idéntico, por lo que no coincidirán correctamente, incluso aunque se ven igual cuando se imprimen.

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

 3
Author: Soviut,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
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
Author: Carl Manaster,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-29 17:54:28

El JUnit assertEquals(obj1, obj2) de hecho llama obj1.equals(obj2).

También hay assertSame(obj1, obj2) que hace obj1 == obj2 (es decir, verifica que obj1 y obj2 están haciendo referencia a la misma instancia), que es lo que estás tratando de evitar.

Así que estás bien.

 3
Author: Jack Leow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-29 18:06:12

"El operador == comprueba si dos Objects son exactamente iguales Object."

Http://leepoint.net/notes-java/data/strings/12stringcomparison.html

String es un Object en java, por lo que cae en esa categoría de reglas de comparación.

 1
Author: Zachery Delafosse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-20 19:44:02