¿Cómo funciona Java Store Strings y cómo funciona la subcadena internamente?

class StringTesting { public static void main(String args[]) { String str = "abcd"; String str1 = new String("abcd"); String str2 = str.substring(0,2); String str3 = str.substring(0,2); String str4 = str.substring(0,str.length()); String str5 = str1.substring(0,2); String str6 = str1.substring(0,2); String str7 = str1.substring(0,str1.length()); System.out.println(str2 == str3); System.out.println(str == str4); System.out.println(str5 == str6); System.out.println(str1 == str7); } } 

Aquí está la salida que obtengo en java 1.6.0_27:

 false true false true 

¿Alguien puede explicar la salida? Sé que Java diferencia entre String almacenado en heap y String almacenado en String “common pool” (que puede ser internado). Internamente, ¿cómo es su representación diferente? ¿Cómo cambia el algoritmo de la subcadena? Favor de citar el libro / artículo / blogs, etc. cuando corresponda.

Ver los comentarios:

  String str = "abcd"; // new String LITERAL which is interned in the pool String str1 = new String("abcd"); // new String, not interned: str1 != str String str2 = str.substring(0,2); // new String which is a view on str String str3 = str.substring(0,2); // same: str3 != str2 String str7 = str1.substring(0,str1.length()); // special case: str1 is returned 

Notas:

  • Desde Java 7u6, la subcadena devuelve una nueva cadena en lugar de una vista en la cadena original (pero eso no hace una diferencia para ese ejemplo)
  • Caso especial cuando llamas a str1.substring(0,str1.length()); – ver código:

     public String substring(int beginIndex, int endIndex) { //some exception checking then return ((beginIndex == 0) && (endIndex == value.length)) ? this : new String(value, beginIndex, subLen); } 

EDITAR

¿Qué es una vista?

Hasta Java 7u6, una Cadena es básicamente una char[] que contiene los caracteres de la cuerda con un desplazamiento y un conteo (es decir, la cuerda se compone de caracteres de count comenzando desde la posición de offset en el char[] ).

Cuando se llama a subcadena, se crea una nueva cadena con el mismo char[] pero un desplazamiento / conteo diferente, para crear efectivamente una vista en la cadena original. (Excepto cuando count = length y offset = 0 como se explicó anteriormente).

Desde java 7u6, se crea un nuevo char[] cada vez, porque no hay más campos de count o offset en la clase de cadena.

¿Dónde se almacena exactamente el conjunto común?

Esto es específico de la implementación. La ubicación de la agrupación se ha movido en versiones recientes. En versiones más recientes, se almacena en el montón.

¿Cómo se maneja el grupo?

Características principales:

  • Los literales de cadena se almacenan en el grupo
  • Las cadenas internas se almacenan en el conjunto ( new String("abc").intern(); )
  • Cuando se encuetra una cadena S (porque es un literal o porque se llama intern() ), la JVM devolverá una referencia a una cadena en la agrupación si hay una que sea equals a S (de ahí "abc" == "abc" siempre debe volverse verdadero).
  • Las cadenas en el grupo pueden ser basura recolectada (lo que significa que una cadena interna podría ser eliminada del grupo en algún momento si se llena)

String es un objeto inmutable.

String#subString – crea una nueva String. Fuente

En código es [abrir jdk 6] –

  public String substring(int beginIndex, int endIndex) { if (beginIndex < 0) { throw new StringIndexOutOfBoundsException(beginIndex); } if (endIndex > value.length) { throw new StringIndexOutOfBoundsException(endIndex); } int subLen = endIndex - beginIndex; if (subLen < 0) { throw new StringIndexOutOfBoundsException(subLen); } return ((beginIndex == 0) && (endIndex == value.length)) ? this : new String(value, beginIndex, subLen); }