metodo equal ejemplo java comparison equals equality

ejemplo - is equal java



Cuando ""== s es falso pero "".equals(s) es verdadero (10)

EDITAR Gracias por las prontas respuestas. Por favor mira cuál es la verdadera pregunta. Lo hice audaz esta vez.

Entiendo la diferencia entre == y .equals. Entonces, esa no es mi pregunta (de hecho, agregué un contexto para eso)

Estoy realizando la validación a continuación para cadenas vacías:

if( "" == value ) { // is empty string }

En el pasado, cuando se obtenían valores del db o se deserializaban objetos de otro nodo, esta prueba falló , porque las dos instancias de cadena eran de hecho referencias de objetos diferentes, aunque contenían los mismos datos.

Entonces la solución para esas situaciones era

if( "".equals( value ) ) { // which returns true for all the empty strings }

Estoy bien con eso. Eso está claramente entendido.

Hoy esto sucedió una vez más, pero me desconcertó porque esta vez la aplicación es una aplicación autónoma muy pequeña que no usa ninguna red , por lo que no se extrae ninguna cadena de la base de datos ni se deserizaliza desde otro nodo.

Entonces la pregunta es:


Bajo qué OTRAS circunstancias:

"" == value // yields false

y

"".equals( value ) // yields true

Para una aplicación independiente local?

Estoy bastante seguro de que no se está usando el nuevo String () en el código.

Y la única forma en que una referencia de cadena podría ser "" es porque se está asignando "" directamente en el código (o eso es lo que yo pensaba) como en:

String a = ""; String b = a; assert "" == b ; // this is true

De alguna manera (después de leer el código más tengo una pista) se crearon dos referencias diferentes de objetos de cadenas vacías, me gustaría saber cómo

Más en la línea de respuesta jjnguys:

¡Byte!

EDITAR: Conclusión

Encontré la razón.

Después de la sugerencia jjnguy, pude mirar con otros ojos el código.

El método culpable: StringBuilder.toString ()

Un nuevo objeto String se asigna e inicializa para contener la secuencia de caracteres actualmente representada por este objeto.

Doh! ...

StringBuilder b = new StringBuilder("h"); b.deleteCharAt( 0 ); System.out.println( "" == b.toString() ); // prints false

Misterio resuelto.

El código usa StringBuilder para lidiar con una cadena cada vez mayor. Resulta que en algún momento alguien lo hizo:

public void someAction( String string ) { if( "" == string ) { return; } deleteBankAccount( string ); }

y use

someAction( myBuilder.toString() ); // bug introduced.

ps ¿He leído demasiado CodingHorror últimamente? ¿O por qué siento la necesidad de agregar algunas imágenes divertidas de animales aquí?


¿Esperaría que "abcde".substring(1,2) y "zbcdefgh".substring(1,2) produzcan el mismo objeto String?

Ambos producen subcadenas "iguales" extraídas de dos cadenas diferentes, pero parece bastante razonable que sean diferentes objetos, por lo que == los ve como diferentes.

Ahora considere cuándo la subcadena tiene longitud 0, substring(1, 1) . Otorga una Cadena de longitud cero, pero no es sorprendente que la "abcde".substring(1,1) sea ​​un objeto diferente de "zbcdefgh".substring(1,2) y, por lo tanto, al menos una de ellas sea un objeto diferente de "".


Como lo entiendo, al compilar el código Java para bytecode o al ejecutar el programa, las mismas cadenas se referenciarán al mismo objeto en la mayoría de los casos para ahorrar memoria. Entonces a veces te salgas con la == comparaciones de cadenas. Pero esta es una optimización del compilador en la que no puede confiar.

Pero a veces sucede que el compilador decide no hacer esta optimización o no hay forma de que el programa vea que las cadenas son las mismas y, de repente, la verificación falla, ya que depende de algún vudú de optimización subyacente que dependa de implementación de jvm que está utilizando, etc.

Entonces, usar iguales siempre es lo mejor que puedes hacer. Para cadenas vacías hay otras posibilidades como comparar con longitud == 0 o si no te importa la compatibilidad hacia atrás hay string.empty ().


Debería intentar considerar String.length() == 0 .


El javadoc para String.intern() tiene algunos buenos comentarios sobre == vs. .equals() .

La documentación también aclara que cada literal de cadena es intern .

Pasante de cadena pública ()

Devuelve una representación canónica para el objeto de cadena.

Un conjunto de cadenas, inicialmente vacío, se mantiene en privado por la clase String.

Cuando se invoca el método interno, si el grupo ya contiene una cadena igual a este objeto String según lo determinado por el método equals (Object), se devuelve la cadena del grupo. De lo contrario, este objeto String se agrega al grupo y se devuelve una referencia a este objeto String.

Se deduce que para cualquier dos cadenas s y t, s.intern () == t.intern () es verdadero si y solo si s.equals (t) es verdadero.

Todas las cadenas literales y las expresiones constantes con valores de cadena se internan. Los literales de cadena se definen en §3.10.5 de la especificación de lenguaje Java

Devuelve: una cadena que tiene los mismos contenidos que esta cadena, pero se garantiza que proviene de un conjunto de cadenas únicas.


Por qué no usar:

if (value != null && value.length == 0) { // do stuff (above could be "== null ||" }

Debería usar equals() porque == para objetos compara referencias, es decir, ¿son el mismo objeto? Mientras que en tiempo de compilación Java encuentra cadenas idénticas y les hace compartir la misma referencia (Las cadenas son inmutables), en tiempo de ejecución es fácil crear cadenas vacías que tienen referencias diferentes, donde == falla para su intención típica de equals() .


Si puedes agarrar el libro Java Puzzlers de Joshua Bloch y Neal Gafter, y mira el rompecabezas 13, "Animal Farm" ... él tiene un gran consejo sobre este tema. Voy a copiar algunos textos relevantes:

"Puede ser consciente de que las constantes de tiempo de compilación de tipo String están intercaladas [JLS 15.28]. En otras palabras, dos expresiones constantes de tipo String que designen la misma secuencia de caracteres están representadas por referencias de objeto idénticas ... Su código debería raramente Si alguna vez, dependa del interning de las constantes de cadena. El internamiento se diseñó únicamente para reducir la huella de memoria de la máquina virtual, no como una herramienta para programadores ... Al comparar referencias de objetos, debe usar el método equals que el == operador a menos que necesite comparar la identidad del objeto en lugar del valor ".

Es de la referencia anterior que mencioné ... páginas 30 - 31 en mi libro.


Si utiliza la búsqueda por código de google, puede encontrar muchos lugares donde las personas cometen el mismo error: google for file: .java / = / = / / "/" Por supuesto, esto puede ser un modismo correcto en circunstancias cuidadosamente controladas, pero por lo general, es solo un error.



"" == value // yields false

y

"".equals( value ) // yields true

cada vez que el valor del valor de la variable no ha sido internado. Este será el caso si el valor se calcula en tiempo de ejecución. Consulte la sección 3.10.5 Literales de cadena de JLS, por ejemplo, un código que ilustra esto:

Por lo tanto, el programa de prueba que consiste en la unidad de compilación (§7.3):

package testPackage; class Test { public static void main(String[] args) { String hello = "Hello", lo = "lo"; System.out.print((hello == "Hello") + " "); System.out.print((Other.hello == hello) + " "); System.out.print((other.Other.hello == hello) + " "); System.out.print((hello == ("Hel"+"lo")) + " "); System.out.print((hello == ("Hel"+lo)) + " "); System.out.println(hello == ("Hel"+lo).intern()); } } class Other { static String hello = "Hello"; }

y la unidad de compilación:

package other; public class Other { static String hello = "Hello"; }

produce la salida:

true true true true false true

Este ejemplo ilustra seis puntos:

  • Las cadenas literales dentro de la misma clase (§8) en el mismo paquete (§7) representan referencias al mismo objeto String (§4.3.1).
  • Las cadenas literales dentro de diferentes clases en el mismo paquete representan referencias al mismo objeto String.
  • Las cadenas literales dentro de diferentes clases en diferentes paquetes también representan referencias al mismo objeto String.
  • Las cadenas calculadas por expresiones constantes (§15.28) se calculan en tiempo de compilación y luego se tratan como si fueran literales.
  • Las cadenas calculadas en el tiempo de ejecución son de nueva creación y, por lo tanto, distintas.
  • El resultado de internar explícitamente una cadena calculada es la misma cadena que cualquier cadena literal preexistente con los mismos contenidos.

String s = ""; String s2 = someUserInputVariale.toLowercase(); // where the user entered in ""

Algo así causaría s == s2 para evaluar a falso.

Gran cantidad de código crea nuevas Strings sin exponer la llamada a una new String() .