h1

Strings en Java

24 agosto 2009

Si tenemos el siguiente código:

public class Warp {
public static void main(String[] args) {
System.out.println("¿Hola cómo estás?");
}
private static final String HOLA = "¿Hola cómo estás?";
private static final Warper warper = new Warper();
}

Si nos preguntan cuál es el resultado de ejecutar este código sabiendo que la clase Wraper no produce ningún resultad. ¿Qué responderías? Si la
respuesta es otra a parte de: “No lo sé, depende de lo que haga Wraper”

En este caso el resultado sería:

C:> java Warp <ENTER>
“Java es sexy”

El código de la clase Wraper:

import java.lang.reflect.*;

public class Warper {
private static Field stringValue;
static {
// String tiene un atributo privado char[] llamado value
try {
stringValue = String.class.getDeclaredField("value");
} catch(NoSuchFieldException ex) {
// Por si la VM tiene un nombre diferente para el atributo
Field[] all = String.class.getDeclaredFields();
for (int i=0; stringValue == null &amp;&amp; i&lt;all.length; i++) {
if (all[i].getType().equals(char[].class)) {
stringValue = all[i];
}
}
}
if (stringValue != null) {
stringValue.setAccessible(true); // Combertir el atributo
}
}
public Warper() {
try {
stringValue.set(
"¿Hola cómo estás?",
"Java es sexy".
toCharArray());
stringValue.set("Adios", "Hola".toCharArray());
} catch(IllegalAccessException ex) {}
}
}

La pregunta ahora es: ¿Cómo es esto posible? ¿Cómo puede manipularse una cadena en una parte distinta del programa? Para entender este caso tenemos mirar
la especificación de java, la cuál dice:

“Each string literal is a reference to an instance of class String. String objects have a constant value. String literals-or, more generally, strings that are the values of constant
expressions-are “interned” so as to share unique instances, using the method String.intern.”

Evidentemente, usaremos menos memoria, si usamos dos Strings que son equivalentes apuntando al mismo objeto. Además, la especificación también dice:

1. Literal strings within the same class in the same package represent references to the same String object.
2. Literal strings within different classes in the same package represent references to the same String object.
3. Literal strings within different classes in different packages likewise represent references to the same String object.
4. Strings computed by constant expressions are computed at compile time and then treated as if they were literals.
5. Strings computed by concatenation at run time are newly created and therefore distinct.

Esto quiere decir, que si una clase de otro paquete juguetea con una cadena “interned” podemos tener un pequeño problema.

El siguiente ejemplo tiene que ver con el HashCode, que por motivos de rendimiento se cachea. Veamos el ejemplo:

public class CachingHashcode {
public static void main(String[] args) {
java.util.Map map = new java.util.HashMap();
map.put("Hola", "Has encontrado el valor");
new Warper();
System.out.println(map.get("Hola"));
System.out.println(map);
}
private static final String greeting = "Hola";
}

En JDK 1.3 el resultado es:

Has encontrado el valor
{Hola !=Has encotrado el valor}

En JDK 1.2 el resultado es:

null
{Hola !=Has encotrado el valor}

Esto ocurre porque en JDL 1.3 el HashCode se cachea, si se calcula una vez, no se recalcula y si cambian los valores de los campos, el HashCode sigue
siendo el mismo.

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: