¿Cuál es el propósito de la expresión "nueva cadena (...)" en Java?

Resuelto Uri asked hace 15 años • 9 respuestas

Al mirar ejemplos de código en línea, a veces me he encontrado con una asignación de una constante String a un objeto String mediante el uso del nuevo operador.

Por ejemplo:

String s;
...
s = new String("Hello World");

Esto, por supuesto, en comparación con

s = "Hello World";

No estoy familiarizado con esta sintaxis y no tengo idea de cuál sería el propósito o efecto. Dado que las constantes de cadena generalmente se almacenan en el grupo de constantes y luego en cualquier representación que tenga la JVM para tratar con constantes de cadena, ¿se asignaría algo en el montón?

Uri avatar Dec 24 '08 10:12 Uri
Aceptado

El único lugar donde puede pensar que desea new String(String)es forzar una copia distinta de la matriz de caracteres interna, como en

small=new String(huge.substring(10,20))

Sin embargo, lamentablemente este comportamiento no está documentado y depende de la implementación.

Esto me ha quemado al leer archivos grandes (algunos de hasta 20 MiB) en una cadena y dividirlos en líneas después del hecho. Terminé con todas las cadenas para las líneas que hacen referencia al carácter [] que consta del archivo completo. Desafortunadamente, eso involuntariamente mantuvo una referencia a toda la matriz para las pocas líneas que conservé durante más tiempo que el procesamiento del archivo; me vi obligado a utilizarlo new String()para solucionarlo, ya que procesar 20,000 archivos muy rápidamente consumía enormes cantidades de RAM.

La única forma independiente de la implementación de hacer esto es:

small=new String(huge.substring(10,20).toCharArray());

Desafortunadamente, esto debe copiar la matriz dos veces, una vez para toCharArray()y otra en el constructor String.

Es necesario que exista una forma documentada de obtener una nueva cadena copiando los caracteres de una existente; o es necesario mejorar la documentación String(String)para hacerla más explícita (hay una implicación allí, pero es bastante vaga y abierta a interpretación).

El peligro de asumir lo que el médico no dice

En respuesta a los comentarios, que siguen llegando, observe cuál new String()fue la implementación de Apache Harmony:

public String(String string) {
    value = string.value;
    offset = string.offset;
    count = string.count;
}

Así es, no hay ninguna copia de la matriz subyacente allí. Y, sin embargo, todavía se ajusta a la documentación de cadenas (Java 7), en el sentido de que:

Inicializa un objeto String recién creado para que represente la misma secuencia de caracteres que el argumento; en otras palabras, la cadena recién creada es una copia de la cadena del argumento. A menos que se necesite una copia explícita del original, el uso de este constructor no es necesario ya que las cadenas son inmutables.

La parte más destacada es "copia de la cadena de argumento "; no dice "copia de la cadena de argumento y la matriz de caracteres subyacente que respalda la cadena".

Tenga cuidado de programar según la documentación y no una implementación .

Lawrence Dol avatar Dec 24 '2008 05:12 Lawrence Dol

La única vez que encontré esto útil es al declarar variables de bloqueo:

private final String lock = new String("Database lock");

....

synchronized(lock)
{
    // do something
}

En este caso, las herramientas de depuración como Eclipse mostrarán la cadena cuando enumeren los bloqueos que un hilo tiene actualmente o está esperando. Debe utilizar "nueva cadena", es decir, asignar un nuevo objeto de cadena, porque de lo contrario un literal de cadena compartido podría bloquearse en algún otro código no relacionado.

Dave Ray avatar Dec 24 '2008 04:12 Dave Ray

Cadena s1="foo"; literal irá en StringPool y s1 hará referencia.

Cadena s2="foo"; esta vez comprobará que el literal "foo" ya esté disponible en StringPool o no, ya que existe ahora, por lo que s2 hará referencia al mismo literal.

Cadena s3 = nueva cadena ("foo"); El literal "foo" se creará primero en StringPool y luego a través del constructor string arg. Se creará el objeto String, es decir, "foo" en el montón debido a la creación del objeto a través del nuevo operador y luego s3 lo referirá.

Cadena s4 = nueva cadena ("foo"); igual que s3

entonces System.out.println(s1==s2); // verdadero debido a una comparación literal.

y System.out.println(s3==s4); // falso debido a la comparación de objetos (s3 y s4 se crean en diferentes lugares del montón)

Vikas avatar Jan 18 '2014 19:01 Vikas

La única utilidad para este constructor descrita por Software Monkey y Ruggs parece haber desaparecido de JDK7. Ya no hay un offsetcampo en la clase String y la subcadena siempre se usa

Arrays.copyOfRange(char[] original, int from, int to) 

para recortar la matriz de caracteres para la copia.

MasterKiller avatar Sep 11 '2013 12:09 MasterKiller