Java Challengers # 2: Comparación de cadenas
Como siempre, tenemos mucho retraso para el comienzo del curso, así que ayer tuvimos una segunda lección entre el nuevo hilo "Java Developer" . Pero esto es así, pequeñas cosas en la vida, pero por ahora seguimos publicando una serie de artículos de Java Challengers, cuya traducción ha sido preparada para usted.
En Java, la clase String
encapsula una matriz de caracteres ( nota del traductor: con java 9 ya es una matriz de byte
, consulte Cadenas compactas en Java 9 ). En términos simples, String
es una matriz de caracteres utilizados para componer palabras, oraciones u otras construcciones.
La encapsulación es uno de los conceptos más poderosos en la programación orientada a objetos. Gracias a la encapsulación, no necesita saber cómo funciona la clase String
. Solo necesita conocer los métodos de su interfaz.

Cuando observa la clase String
en Java, puede ver cómo se encapsula la matriz de caracteres:
public String(char value[]) { this(value, 0, value.length, null); }
Para comprender mejor la encapsulación, imagine un objeto físico: una máquina. ¿Necesita saber cómo funciona un automóvil debajo del capó para conducirlo? Por supuesto que no, pero debe saber qué hacen las interfaces del automóvil: el acelerador, los frenos y el volante. Cada una de estas interfaces admite ciertas acciones: aceleración, frenado, girar a la izquierda, girar a la derecha. Lo mismo es cierto en la programación orientada a objetos.
El primer artículo de la serie Java Challengers fue sobre la sobrecarga de métodos, que se usa ampliamente en la clase String
. La sobrecarga puede hacer que tus clases sean realmente flexibles:
public String(String original) {} public String(char value[], int offset, int count) {} public String(int[] codePoints, int offset, int count) {} public String(byte bytes[], int offset, int length, String charsetName) {}
En lugar de tratar de entender cómo funciona la clase String
, este artículo lo ayudará a comprender lo que hace y cómo usarlo en su código.
¿Qué es un conjunto de cadenas?
La clase String
es posiblemente la clase más utilizada en Java. Si creamos un nuevo objeto en la memoria dinámica (montón de memoria) cada vez que usamos String
, desperdiciaremos mucha memoria. El conjunto de cadenas resuelve este problema almacenando solo un objeto para cada valor de fila.

Grupo de líneas en fila
Aunque creamos varias variables de String
con los valores Duke
y Juggy
, solo se crean y almacenan dos objetos en la memoria dinámica (montón). Vea el siguiente ejemplo de código para la prueba. (Recuerde que en Java, el operador " ==
" se usa para comparar dos objetos y determinar si el mismo objeto es el mismo o no).
String juggy = "Juggy"; String anotherJuggy = "Juggy"; System.out.println(juggy == anotherJuggy);
Este código devolverá true
porque las dos variables de String
apuntan al mismo objeto en el grupo de cadenas. Sus significados son los mismos.
La excepción es el new
operador.
Ahora mire este código: se parece al ejemplo anterior, pero hay una diferencia.
String duke = new String("duke"); String anotherDuke = new String("duke"); System.out.println(duke == anotherDuke);
Según el ejemplo anterior, puede pensar que este código devolverá true
, pero no lo es. Agregar un new
operador crea un nuevo objeto String
en la memoria. Por lo tanto, la JVM creará dos objetos diferentes.
Métodos nativos
Los métodos nativos en Java son métodos que se compilarán utilizando el lenguaje C, generalmente con el objetivo de administrar la memoria y optimizar el rendimiento.
Agrupaciones de cadenas y método intern()
Para almacenar cadenas en una agrupación, se utiliza un método llamado intercalación de cadenas.
Esto es lo que Javadoc nos dice sobre el método intern()
:
public native String intern();
El método intern()
se usa para almacenar cadenas en un grupo de cadenas. Primero, verifica si una fila ya creada existe en el grupo. Si no, crea una nueva fila en el grupo. La lógica del grupo de filas se basa en el patrón Flyweight .
Ahora, observe lo que sucede cuando usamos new
para crear dos líneas:
String duke = new String("duke"); String duke2 = new String("duke"); System.out.println(duke == duke2);
A diferencia del ejemplo anterior con la new
palabra clave, en este caso la comparación devolverá true
. Esto se debe a que el uso del método intern()
garantiza que la cadena se encuentre en el grupo.
Método equals
en String
clase String
El método equals()
se usa para verificar si dos clases son iguales o no. Como equals()
se encuentra en la clase Object
, cada clase Java la hereda. Pero el método equals()
debe ser anulado para que funcione correctamente. Por supuesto, String
anula equals()
.
Echa un vistazo:
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String aString = (String)anObject; if (coder() == aString.coder()) { return isLatin1() ? StringLatin1.equals(value, aString.value) : StringUTF16.equals(value, aString.value); } } return false; }
Como puede ver, el valor de la clase String
se compara a través de equals()
y no a través de una referencia de objeto. No importa si las referencias a los objetos son diferentes; Las condiciones serán comparadas.
Métodos de String
comunes
Hay una cosa más que debe saber antes de resolver el problema de comparación de cadenas.
Considere los métodos más comunes de la clase String
:
Resolver el problema de comparación de cadenas
Verifiquemos lo que aprendió sobre la clase String
resolviendo un pequeño rompecabezas.
En esta tarea, compara varias líneas usando los conceptos que ha aprendido. Mirando el código a continuación, ¿puedes determinar el valor de cada result
variable?
public class ComparisonStringChallenge { public static void main(String... doYourBest) { String result = ""; result += " powerfulCode ".trim() == "powerfulCode" ? "0" : "1"; result += "flexibleCode" == "flexibleCode" ? "2" : "3"; result += new String("doYourBest") == new String("doYourBest") ? "4" : "5"; result += new String("noBugsProject") .equals("noBugsProject") ? "6" : "7"; result += new String("breakYourLimits").intern() == new String("breakYourLimits").intern() ? "8" : "9"; System.out.println(result); } }
¿Cuál será la conclusión?
- A: 02468
- B: 12469
- C: 12579
- D: 12568
La respuesta correcta se da al final del artículo.
Que paso ahora Comprender String
comportamiento de las String
En la primera línea vemos:
result += " powerfulCode ".trim() == "powerfulCode" ? "0" : "1";
En este caso, el resultado es false
, porque cuando el método trim()
elimina espacios, crea una nueva String
utilizando el new
operador.
A continuación vemos:
result += "flexibleCode" == "flexibleCode" ? "2" : "3";
No hay ningún secreto aquí; las filas son las mismas en el grupo de filas. Esta comparación devuelve true
.
Entonces, tenemos:
result += new String("doYourBest") == new String("doYourBest") ? "4" : "5";
El uso de new
pistas conduce a la creación de dos nuevas líneas y no importa si sus valores son iguales o no. En este caso, la comparación será false
incluso si los valores son los mismos.
Siguiente:
result += new String("noBugsProject") .equals("noBugsProject") ? "6" : "7";
Como usamos el método equals()
, se comparará el valor de la cadena, no la instancia del objeto.
En este caso, no importa si hay diferentes objetos o no, ya que se compara el valor. El resultado es true
.
Finalmente tenemos:
result += new String("breakYourLimits").intern() == new String("breakYourLimits").intern() ? "8" : "9";
Como viste anteriormente, el método intern()
coloca una cadena en un grupo de cadenas. Ambas líneas apuntan al mismo objeto, por lo que en este caso es true
.
Errores de cadena comunes
Puede ser difícil determinar si dos líneas apuntan al mismo objeto o no, especialmente cuando las líneas contienen el mismo valor. Es útil recordar que usar new
siempre conduce a la creación de un nuevo objeto en la memoria, incluso si los valores de cadena son los mismos.
El uso de métodos de String
para comparar referencias de objetos también puede ser complicado. La peculiaridad es que si el método cambia algo en la línea, habrá diferentes referencias a los objetos.
Algunos ejemplos para ayudar a aclarar:
System.out.println("duke".trim() == "duke".trim());
Esta comparación será verdadera porque el método trim()
no crea una nueva línea.
System.out.println(" duke".trim() == "duke".trim());
En este caso, el primer método trim()
genera una nueva línea, ya que el método hará su trabajo y, por lo tanto, los enlaces serán diferentes.
Finalmente, cuando trim()
hace su trabajo, crea una nueva línea:
Que recordar acerca de las cuerdas
Las filas no son mutables, por lo que el estado de la fila no se puede cambiar.
Para ahorrar memoria, la JVM almacena cadenas en un grupo de cadenas. Al crear una nueva línea, la JVM verifica su valor y apunta a un objeto existente. Si el grupo no tiene una fila con este valor, la JVM crea una nueva fila.
El operador " ==
" compara referencias de objetos. El método equals()
compara valores de cadena. La misma regla se aplicará a todos los objetos.
Al usar el new
operador, se creará una nueva línea en el montón (Nota del traductor: está escrito en el original que está en el grupo, pero esto no es así, gracias zagayevskiy ), incluso si hay una línea con el mismo valor.
La respuesta
La respuesta a este problema es D. La conclusión será 12568.
Continuará ...