sirve que para isempty how empty check java string comparison string-comparison

que - Comparando una cadena con la cadena vacía(Java)



java isempty null (8)

Tengo una pregunta sobre la comparación de una cadena con la cadena vacía en Java. ¿Hay alguna diferencia si comparo una cadena con la cadena vacía con == o equals ? Por ejemplo:

String s1 = "hi"; if (s1 == "")

o

if (s1.equals(""))

Sé que uno debe comparar cadenas (y objetos en general) con equals , y no == , pero me pregunto si importa para la cadena vacía.


Está un poco a un lado de tu pregunta original, pero siempre hay

if(s1.length() == 0)

Creo que esto es equivalente al método isEmpty () de 1.6.


Una cadena, es una cadena, es una cadena, ya sea la cadena vacía o no. Use equals() .


Va a depender de si la cadena es literal o no. Si creas la cadena con

new String("")

Entonces nunca coincidirá "" con el operador igual, como se muestra a continuación:

String one = ""; String two = new String(""); System.out.println("one == /"/": " + (one == "")); System.out.println("one.equals(/"/"): " + one.equals("")); System.out.println("two == /"/": " + (two == "")); System.out.println("two.equals(/"/"): " + two.equals(""));

-

one == "": true one.equals(""): true two == "": false two.equals(""): true

Básicamente, quieres usar siempre iguales ()


"".equals(s)

Parece ser la mejor opción, pero también hay Stringutils.isEmpty(s) en la biblioteca común de Apache.


Dadas dos cadenas:

String s1 = "abc"; String s2 = "abc";

-o bien

String s1 = new String("abc"); String s2 = new String("abc");

El operador == realizado en dos objetos comprueba la identidad del objeto (devuelve verdadero si los dos operadores vuelven a la misma instancia de objeto). El comportamiento real de == aplicado a java.lang.Strings no siempre parece ser consistente debido a Interno de cadenas

En Java, las cadenas se internan (al menos parcialmente a discreción de la JVM). En cualquier momento, s1 y s2 pueden o no haberse internado para ser la misma referencia de objeto (suponiendo que tengan el mismo valor). s1 == s2 puede o no devolver verdadero, basándose únicamente en si s1 y s2 han sido internados.

Hacer que s1 y s2 sean iguales a Cadenas vacías no tiene ningún efecto sobre esto; aún pueden haber sido internados o no.

En resumen, == puede o no devolver verdadero si s1 y s2 tienen el mismo contenido. s1.equals (s2) se garantiza que devuelve verdadero si s1 y s2 tienen el mismo contenido.


s1 == ""

no es confiable ya que prueba igualdad de referencia no igualdad de objeto (y String no es estrictamente canónico).

s1.equals("")

es mejor, pero puede sufrir excepciones de puntero nulo. Mejor aún es:

"".equals(s1)

Sin excepciones de puntero nulo.

EDITAR: Ok, se preguntó sobre la forma canónica . Este artículo lo define como:

Supongamos que tenemos algún conjunto S de objetos, con una relación de equivalencia. Una forma canónica se da al designar algunos objetos de S para que sean "en forma canónica", de modo que cada objeto bajo consideración sea equivalente a exactamente un objeto en forma canónica.

Para darle un ejemplo práctico: tome el conjunto de números racionales (o "fracciones" son comúnmente llamados). Un número racional consiste en un numerador y un denomoinator (divisor), ambos son enteros. Estos números racionales son equivalentes:

3/2, 6/4, 24/16

Los nubmers racionales generalmente se escriben de manera que el gcd (máximo divisor común) es 1. Entonces todos se simplificarán a 3/2. 3/2 se puede ver como la forma canónica de este conjunto de números racionales.

Entonces, ¿qué significa en programación cuando se usa el término "forma canónica"? Puede significar un par de cosas. Tomemos como ejemplo esta clase imaginaria:

public class MyInt { private final int number; public MyInt(int number) { this.number = number; } public int hashCode() { return number; } }

El código hash de la clase MyInt es una forma canónica de esa clase porque para el conjunto de todas las instancias de MyInt, puede tomar cualquier dos elementos m1 y m2 y obedecerán la siguiente relación:

m1.equals(m2) == (m1.hashCode() == m2.hashCode())

Esa relación es la esencia de la forma canónica. Una forma más común de que surja esto es cuando usa métodos de fábrica en clases tales como:

public class MyClass { private MyClass() { } public MyClass getInstance(...) { ... } }

Las instancias no se pueden instanciar directamente porque el constructor es privado. Este es solo un método de fábrica. Lo que un método de fábrica le permite hacer es cosas como:

  • Siempre devuelva la misma instancia (singleton abstraído);
  • Simplemente crea una nueva intsance con cada llamada;
  • Devuelve objetos en forma canónica (más sobre esto en un segundo); o
  • lo que quieras.

Básicamente, el método de fábrica resume la creación de objetos y, personalmente, creo que sería una función de lenguaje interesante obligar a todos los constructores a ser privados para hacer cumplir el uso de este patrón, pero me estoy desviando.

Lo que puede hacer con este método de fábrica es almacenar en caché las instancias que crea de manera tal que para dos instancias s1 y s2 obedezcan la siguiente prueba:

(s1 == s2) == s1.equals(s2)

Entonces, cuando digo que String no es estrictamente canónico, significa que:

String s1 = "blah"; String s2 = "blah"; System.out.println(s1 == s2); // true

Pero como otros se han atenuado, puedes cambiar esto usando:

String s3 = new String("blah");

y posiblemente:

String s4 = String.intern("blah");

Por lo tanto, no puede confiar completamente en la igualdad de referencia, por lo que no debe confiar en ella en absoluto.

Como una advertencia al patrón anterior, debo señalar que el control de la creación de objetos con constructores privados y métodos de fábrica no garantiza que la igualdad de referencia signifique igualdad de objetos debido a la serialización. La serialización evita el mecanismo normal de creación de objetos. Josh Bloch cubre este tema en Effective Java (originalmente en la primera edición cuando habló sobre el patrón de enum de tipo seguro que más tarde se convirtió en una característica del lenguaje en Java 5) y puede evitarlo al sobrecargar el método (privado) readResolve (). Pero es complicado. Los cargadores de clase también afectarán el problema.

De todos modos, esa es la forma canónica.



Respuesta corta

s1 == "" // No! s1.equals("") // Ok s1.isEmpty() // Ok: fast (from Java 1.6) "".equals(s1) // Ok: null safe

Me gustaría asegurar que s1 no sea nulo y use isEmpty ().

Nota: la cadena vacía "" no es una cadena especial, pero cuenta como cualquier otro "valor".

Un poco más de respuesta

Las referencias a objetos String dependen de la forma en que se crean:

Los objetos de cadena creados con el operador new siempre hacen referencia a objetos separados, incluso si almacenan la misma secuencia de caracteres de modo que:

String s1 = new String(""); String s2 = new String(""); s1 == s2 // false

Los objetos de cadena creados con operator = seguidos de un valor entre comillas dobles ( = "valor" ) se almacenan en un grupo de objetos String: antes de crear un nuevo objeto en el grupo, se busca en el grupo un objeto con el mismo valor y referenciado si se encuentra.

String s1 = ""; // "" added to the pool String s2 = ""; // found "" in the pool, s2 will reference the same object of s1 s1 == s2 // true

Lo mismo se aplica a las cadenas creadas que incluyen un valor entre comillas dobles ("valor"), por lo tanto:

String s1 = ""; s1 == ""; //true

Cadena equivale a las verificaciones de método para ambos, por eso es seguro escribir:

s1.equals("");

Esta expresión puede arrojar una NullPointerException si s1 == null, por lo que si no comprueba null antes, es más seguro escribir:

"".equals(s1);

Por favor, lea también ¿Cómo comparo cadenas en Java?

Espero que ayude a los usuarios no tan experimentados, que pueden encontrar otras respuestas demasiado complicadas. :)