reales - ¿Cuál es el propósito de la expresión "new String(...)" en Java?
libro de android studio en español pdf (8)
Bueno, eso depende de qué es "..." en el ejemplo. Si se trata de un StringBuffer, por ejemplo, o una matriz de bytes, o algo así, obtendrá un String construido a partir de los datos que está pasando.
Pero si se trata simplemente de otra Cadena, como en una new String("Hello World!")
, Entonces debería reemplazarse simplemente por "Hello World!"
, en todos los casos. Las cadenas son inmutables, por lo que clonar una no sirve para nada; es más detallado y menos eficiente crear un nuevo objeto String solo para servir como un duplicado de una cadena existente (ya sea una literal u otra variable String que ya tenga).
De hecho, Effective Java (que recomiendo encarecidamente) usa exactamente esto como uno de sus ejemplos de "Evite crear objetos innecesarios":
Como un ejemplo extremo de lo que no debe hacer, considere esta afirmación:
String s = new String("stringette"); **//DON''T DO THIS!**
(Java efectivo, segunda edición)
Mientras busco ejemplos de código en línea, a veces me he encontrado con una asignación de una constante de cadena 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á el propósito o efecto. Dado que las constantes de cadena normalmente se almacenan en el conjunto constante y, luego, en cualquier representación que tenga la JVM para tratar las constantes de cadena, ¿se asignará algo en el montón?
El único lugar donde puede necesitar una new String(String)
es forzar a una subcadena a copiar a una nueva matriz de caracteres subyacente, como en
small=new String(huge.substring(10,20))
Sin embargo, este comportamiento lamentablemente no está documentado y depende de la implementación.
Me he quemado al leer archivos de gran tamaño (algunos hasta 20 MiB) en una cadena y tallar en líneas después del hecho. Terminé con todas las cadenas para las líneas que hacen referencia al carácter [] que consta de todo el archivo. Desafortunadamente, eso involuntariamente mantuvo una referencia a toda la matriz para las pocas líneas que sostuve durante más tiempo que el procesamiento del archivo: me vi obligado a usar una new String()
para evitarlo.
La única forma de implementación agnóstica para hacer esto es:
small=new String(huge.substring(10,20).toCharArray());
Desafortunadamente, esto debe copiar la matriz dos veces, una vez para toCharArray()
y una vez en el constructor de cadenas.
Debe haber una forma documentada de obtener un nuevo String copiando los caracteres de uno existente; o la documentación de String(String)
necesita ser mejorada para hacerlo más explícito (hay una implicación allí, pero es bastante vaga y está abierta a la interpretación).
Peligro de asumir lo que el doctor no dice
En respuesta a los comentarios, que siguen llegando, observe lo que fue la implementación de Apache Harmony del new String()
:
public String(String string) {
value = string.value;
offset = string.offset;
count = string.count;
}
Así es, no hay copia de la matriz subyacente allí. Y, sin embargo, todavía se ajusta a la documentación de la Cadena (Java 7), ya 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 es innecesario ya que las cadenas son inmutables.
La pieza sobresaliente es "copia de la cadena del argumento"; no dice "copia de la cadena de argumento y la matriz de caracteres subyacente que soporta la cadena".
Tenga cuidado de que programe la documentación y no una implementación .
En general, esto indica que alguien no se siente cómodo con el nuevo estilo C ++ de declarar cuando se inicializa.
De vuelta en los días C, no se consideraba una buena forma para definir variables automáticas en un ámbito interno; C ++ eliminó la restricción del analizador y Java extendió eso.
Entonces, ves el código que tiene
int q;
for(q=0;q<MAX;q++){
String s;
int ix;
// other stuff
s = new String("Hello, there!");
// do something with s
}
En el caso extremo, todas las declaraciones pueden estar en la parte superior de una función, y no en ámbitos cerrados como el bucle for
aquí.
En general, sin embargo, el efecto de esto es hacer que una Cadena de caracteres sea llamada una vez, y la Cadena resultante sea desechada. (El deseo de evitar esto es lo que llevó a Stroustrup a permitir declaraciones en cualquier parte del código.) Así que estás en lo correcto al decir que es un estilo innecesario y malo en el mejor de los casos, y posiblemente realmente malo.
Hay dos formas en que se pueden crear cadenas en Java. Los siguientes son los ejemplos de ambas formas: 1) Declare una variable de tipo String (una clase en Java) y asígnela a un valor que se debe poner entre comillas dobles. Esto creará una cadena en el área del grupo de cadenas de la memoria. por ejemplo: String str = "JAVA";
2) Use el constructor de la clase String y pase una cadena (entre comillas dobles) como argumento. por ejemplo: String s = new String ("JAVA"); Esto creará una nueva cadena JAVA en la memoria principal y también en el grupo de cadenas si esta cadena no está presente en el conjunto de cadenas.
La única utilidad para este constructor descrita por Software Monkey and Ruggs parece haber desaparecido de JDK7. Ya no hay un campo de offset
en la clase String, y la subcadena siempre usa
Arrays.copyOfRange(char[] original, int from, int to)
para recortar la matriz de caracteres para la copia.
La única vez que he encontrado esto útil es en 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 se enumere qué elementos bloquea un hilo actualmente almacenado o que está esperando. Debe utilizar "nueva cadena", es decir, asignar un nuevo objeto String, porque de lo contrario un literal de cadena compartida podría estar bloqueado en algún otro código no relacionado.
Supongo que dependerá de las muestras de código que estés viendo.
La mayoría de las veces, usar el constructor de la clase "new String ()" en el ejemplo del código es solo para mostrar una clase java muy conocida en lugar de crear una nueva.
Debe evitar usarlo la mayoría de las veces. No solo porque los literales de cadena están internados, sino principalmente porque las cadenas son inmutables. No tiene sentido tener dos copias que representen el mismo objeto.
Si bien el artículo que menciona Ruggs es "interesante" , no debe usarse a menos que sea en circunstancias muy específicas, ya que podría crear más daño que beneficio. Codificará una implementación en lugar de una especificación y el mismo código no podría ejecutarse de la misma manera, por ejemplo, en JRockit, IBM VM u otro.
String s1 = "foo"; literal irá en StringPool y s1 se referirá.
Cadena s2 = "foo"; esta vez comprobará que el literal "foo" ya está disponible en StringPool o no como ahora existe, por lo que s2 hará referencia al mismo literal.
String s3 = new String ("foo"); El literal "foo" se creará en StringPool primero y luego a través de string arg constructor Se creará String Object, es decir, "foo" en el montón debido a la creación de objetos a través de un nuevo operador, luego s3 lo referirá.
String s4 = new String ("foo"); lo mismo que s3
entonces System.out.println (s1 == s2); // verdadero debido a la 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 en el montón)