¿Cómo se puede inicializar una cadena usando ""?

154

Si String es una clase como cualquier otra, ¿cómo se puede inicializar con comillas dobles?

Splitgames
fuente
25
String es una clase VIP. " "ya es una cadena!
johnchen902
2
Sin significado especial. Solo quise decir muy importante. Es decir, java.lang.Stringtener un tratamiento especial del lenguaje Java.
johnchen902
16
¿Quién dice que la cadena es "una clase como cualquier otra"? Es una clase muy especial, diferente a cualquier otra. Dado que su suposición es falsa, la pregunta no es realmente responsable.
Eric Lippert
55
El hecho de que la suposición sea falsa no significa que la pregunta no tenga respuesta. Y la respuesta correcta ya tiene 197 votos.
Koray Tugay

Respuestas:

293

Java String es especial

Los diseñadores de Java decidieron retener los tipos primitivos en un lenguaje orientado a objetos, en lugar de convertir todo en un objeto, para mejorar el rendimiento del lenguaje. Las primitivas se almacenan en la pila de llamadas, que requieren menos espacios de almacenamiento y son más baratas de manipular. Por otro lado, los objetos se almacenan en el montón de programas, que requieren una gestión de memoria compleja y más espacios de almacenamiento.

Por razones de rendimiento, la cadena de Java está diseñada para estar entre una primitiva y una clase.

Por ejemplo

String s1 = "Hello";              // String literal
String s2 = "Hello";              // String literal
String s3 = s1;                   // same reference
String s4 = new String("Hello");  // String object
String s5 = new String("Hello");  // String object

ingrese la descripción de la imagen aquí

Nota: Los literales de cadena se almacenan en un grupo común. Esto facilita el intercambio de almacenamiento para cadenas con el mismo contenido para conservar el almacenamiento. Stringlos objetos asignados a través de un nuevo operador se almacenan en el heap, y no se comparte el almacenamiento de los mismos contenidos.

Suresh Atta
fuente
72
Tenga en cuenta que el "grupo común" suele formar parte del montón.
Joachim Sauer
3
@JoachimSauer Sí ... con pequeños beneficios :) agregó eso en la nota. Gracias por recordar.
Suresh Atta
2
Entonces, ¿es más rápido escribir String s1 = "Hello"; que String s2 = new String ("Hola") ;?
user2097804
28
Agregaría eso en su ejemplo s1 == s2 == s3 pero s4! = S5
Alfredo Osorio
8
@AndrewJanke en el hotspot reciente jvm (7), el grupo de cadenas no está en perm gen y desde Java 8 ya no hay perm gen ...
assylias
50

Java trata a String como una clase especial, puede inicializar en ambos sentidos

  1. Asignando directamente literal

    String a = "adsasdf";
  2. Como otros objetos que usan una nueva palabra clave

    String a = new String("adsasdf");

Debe tener especial cuidado cuando quiera comparar con el ==signo:

String a = "asdf";
String b = "asdf";
System.out.println(a == b);  // True
System.out.println(a.equals(b)); // True

String a = new String("asdf");
String b = new String("asdf");
System.out.println(a == b);  // False
System.out.println(a.equals(b)); // True

Esto se debe a que, en el primer caso, los objetos a y b se mantienen en algo llamado literal pooly ambos hacen referencia al mismo objeto, por lo que son iguales en ambos sentidos.

Pero en el segundo caso, ayb hace referencia a diferentes objetos, como cuando inicializamos cualquier otro objeto. por lo que son desiguales en comparación con el ==operador, mientras que son iguales en valores.

chetan
fuente
18

La cadena recibe un tratamiento especial en el JLS: es uno de los dos tipos no primitivos para los que existen literales (el otro es Class) * .

De la JLS :

Un literal de cadena es una referencia a una instancia de la clase `String [...].

* bueno, también existe el "tipo nulo" con su "literal nulo" null, pero la mayoría de la gente no piensa en el "tipo nulo" como un tipo apropiado.

Joachim Sauer
fuente
1
Tampoco sabía que el "tipo nulo" es un tipo apropiado en Java. Su información muy útil, debe aumentar el tamaño de la fuente.
Grijesh Chauhan
1
@GrijeshChauhan: bueno, el "tipo nulo" es una redacción ingeniosa que permite nullasignar cualquiera a cualquier variable de tipo de referencia. No es un tipo interesante, de lo contrario.
Joachim Sauer
15

Es una característica del lenguaje Java. Los literales de cadena en el código fuente reciben un tratamiento especial.

La especificación del lenguaje, aquí , simplemente dice que un literal de cadena es de Stringtipo

nos
fuente
5

El texto entre comillas dobles crea un Stringobjeto literal .

String myString = "Some text";

El código anterior crea un Stringobjeto, usando comillas dobles.

tristan2468
fuente
4

Las cadenas se usan muy a menudo en un lenguaje de programación. Como Java está orientado a objetos, una cadena es un objeto. Para evitar la nueva cadena engorrosa ("someString"); cada vez que necesite un objeto de cadena, java le permite crear un objeto de cadena usando el literal de cadena.

Pero debes tener en cuenta la igualdad de cuerdas. Aquí una breve prueba JUnit para demostrar lo que quiero decir.

    @Test
    public void stringTest() {
       // a string literal and a string object created 
       // with the same literal are equal
       assertEquals("string", new String("string"));

       // two string literals are the same string object
       assertSame("string", "string"); 

       // a string literal is not the same object instance 
       // as a string object created with the same string literal
       assertFalse("string" == new String("string"));

       // java's String.intern() method gives you the same
       // string object reference for all strings that are equal.
       assertSame("string", new String("string").intern());
    }
René Link
fuente
Si solo pudiera inicializar una cadena con new String(String src), entonces ni siquiera podría darle al constructor un literal de cadena. Tendría que inicializar a char [], y luego usar el String(char [] src)constructor para construir la cadena, o tendría que leer la cadena de un archivo.
AJMansfield
Eso no es correcto. Un literal de cadena es solo una secuencia de caracteres en un archivo fuente rodeado de comillas dobles. Java crea automáticamente una instancia de una cadena usando este literal. Por lo tanto, un objeto literal y un objeto String son iguales, pero no son lo mismo. Java también podría haberse implementado de esta manera, por lo que debe usar una nueva Cadena (""); instanciar un objeto String, pero esto solo haría nuestra vida más difícil. Entonces, cuando escribe una nueva cadena ("una cadena"), Java crea un objeto de cadena para el literal "una cadena" y pasa este objeto de cadena al constructor de la nueva cadena.
René Link
2

Solo por mencionar. Un literal de cadena es una referencia a una instancia de clase String, puede escribir código como este:

 "abc" .getBytes ();

 "a: b: c" .split (":");

 "愛" .codePointAt (0);
mkdev
fuente
2

- String es una clase en Java . Tiene razón al respecto, por lo que siempre podemos inicializar con la newpalabra clave.

- Pero cuando hacemos algo como:

String s = "";

La declaración anterior está marcada por el compilador como un objeto String especial y luego JVM durante la carga de la clase (la carga se realiza antes de la inicialización), ve esto lo que se conoce como un literal de cadena , que se almacena en un grupo de literales de cadena .

- Por lo tanto, se puede crear una Cadena usando new()y por el ""método, pero este último proporciona un literal de cadena que permanece en el montón incluso cuando no hay referencia a ese objeto de cadena, porque tiene una referencia del grupo de literales de cadena.

Kumar Vivek Mitra
fuente
2

Java hace un proceso de dos pasos para nosotros.

String str = "hello";

es equivalente a

char data[] = {'h', 'e', 'l' , 'l', 'o'};
String str = new String(data);

Al igual que [.NET] [1] tiene algo similar.

String(Char[]) constructor

hace

String(char[] value)

Agregar referencias: -

usuario1769790
fuente
2
El proceso que describe no es lo que Java realmente hace: como ya han dicho otros, "hello"es un literal de cadena y el compilador lo colocará en el grupo constante, consulte JLS §3.10.5 y JVMS §5.1 .
siegi
1

Java.lang.StringNo es solo una clase. Es una parte integral del lenguaje central. El compilador tiene azúcar sintáctica para ello. Por ejemplo, ""es como una abreviatura de new String(""). Cuando se escribe, ""el compilador optimiza cadenas idénticas a la misma instancia para ahorrar espacio."a" + 5 == "a5" ==> true

El compilador tiene azúcar sintáctica para muchas cosas, incluyendo no tener que encajonar / desempaquetar entre versiones de objeto y sus tipos nativos, sin padre significa Objeto, constructor predeterminado, ...

Sylwester
fuente
55
""no es una abreviatura de new String(""). Si lo usa "", lo primero que se hará es buscar coincidencias en el conjunto de cadenas de la JVM y, si eso es cierto, devolverá esa cadena. Al usarlo new String(""), siempre creará una nueva Cadena, incluso si la Cadena misma ya existe en el grupo de Cadena (porque no se almacenará en el grupo de Cadena).
g00glen00b
Actualicé mi respuesta. ¿La gente usa esto para su ventaja, como usar constantes de cadena como un equivalente al tipo de símbolo Lisp?
Sylwester