Operador == y Strings
El operador de igualdad, ==, admite operandos numéricos, booleanos, e igualdad de referencias a objetos.
A tiempo de ejecución, el resultado de ==
es true
si los valores de los operandos son ambos null
o ambos se refieren al mismo objeto o mismo arreglo; de otra manera, el resultado es false
.
Mientras ==
puede ser usado para comparar referencias de tipo String
, ese test de igualdad determina si los dos operandos se refieren al mismo objeto String
. El resultado es false
si los operandos apuntan a distintos objetos Strings
, aún si éstos contienen la misma secuencia de caracteres. El contendido de dos strings s
y t
pueden ser verificados por igualdad invocando s.equals(t)
.
Así fue visto en clases y corresponde a la especificación del lenguaje Java.
Un detalle relevante y significativo, no visto en clases, aparece cuando los operandos son instancias de String
literales. Una vez creado toda instancia de String
es constante en Java (otra opción es crear instancias de StringBuffer
los cuales son mutables, se pueden cambiar). Strings de literales
corresponden a aquellos compuestos por cero o más caracteres encerrados
entre comillas (Ver sección 3.10.5 de la especificación del lenguaje).
La
clase String mantiene una colección inicialmente vacía de strings.
Cuando definimos un string literal en el programa, a tiempo de
compilación éste es agregado a esta colección si la misma secuencia,
determinada por equals(object), no existe aún. Luego en el programa se
ubica la referencia a tal string. Esta operación es conocida como
internar el string. Además cualquier string, no
necesariamente puede ser internado invocando su método intern().
Con esto para el siguiente programa se tiene:
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 en otro archivo (y directorio)
package other;
public class Other { public static String hello = "Hello"; }
produce la salida:
true true true true false true
Este ejemplo ilustra 6 puntos:
* Strings literales dentro de la misma clase en el paquete representan referencias al mismo objeto string.
* Strings literales dentro de diferentes clases en el mismo paquete
representan referencias al mismo objeto string.
*
Strings literales dentro de diferentes clases en diferentes paquete
también representan referencias al mismo objeto string.
* Strings obtenidos a partir de expresiones constantes son
computados en tiempo de compilación y entonces son tratados como si
fueran literales.
* Strings calculados en tiempo de ejecución son creados independientemente y consecuentemente distintos.
* El resultado de internar explícitamente un string
calculado en tiempo de ejecución genera el mismo string que
cualquier pre-existente string literal con el mismo contenido.
Para probar el ejemplo haga:
1.- Cree directorio testPackage.
2.- Cree directorio other.
3.- Cree el archivo Test.java dentro de testPackage y Other.java dentro de other.
4.- Estando en directorio padre de testPackage y other, compile con
$ javac testPackage/Test.java
5.- Finalmente corra el programa con:
$ java testPackage.Test
Puede bajar los archivos desde aquí.