2010-01-05 15 views
85

normalmente Creamos objetos usando la palabra clave new, como:Las cadenas son objetos en Java, entonces ¿por qué no usamos 'nuevo' para crearlos?

Object obj = new Object(); 

Las cadenas son objetos, pero no usamos new para crearlos:

String str = "Hello World"; 

¿Por qué es esto? ¿Puedo hacer una cadena con new?

+0

También debería echar un vistazo a esta pregunta http://stackoverflow.com/questions/456575/java-wrapper- igualdad-prueba – changed

+1

Porque los literales de cadena ya son objetos. – EJP

+0

Tenga en cuenta que 'new String (...)' se ha utilizado para eludir un detalle de implementación cuando se subcadena cadenas grandes. Esto fue arreglado en Java 7 y ya no es necesario. –

Respuesta

113

Además de lo que ya se dijo, Cuerda literales [es decir, cadenas como "abcd" pero no como new String("abcd")] en Java son internados - esto significa que cada vez que se refieren a "ABCD", se obtiene una referencia a una instancia única de String, en lugar de una nueva cada vez. Por lo que tendrá:

String a = "abcd"; 
String b = "abcd"; 

a == b; //True 

pero si tuviera

String a = new String("abcd"); 
String b = new String("abcd"); 

entonces es posible tener

a == b; // False 

(y en caso de que alguien necesita recordar, siempre use .equals() para comparar cadenas; == pruebas de igualdad física).

Los literales de Interning String son buenos porque a menudo se usan más de una vez. Por ejemplo, considere el (artificial) Código:

for (int i = 0; i < 10; i++) { 
    System.out.println("Next iteration"); 
} 

Si no tuviéramos la internación de cadenas "siguiente iteración" tendría que ser instanciado 10 veces, mientras que ahora sólo se crea una instancia de una vez.

+1

Al utilizar String a = new String ("abcd"), ¿significa que hay dos cadenas con contenido similar en la memoria? – changed

+1

Derecha - el compilador no necesariamente verificará si tal cadena ya ha sido internada (aunque ciertamente podría escribir una que sí lo hizo). – danben

+0

sí, esta optimización es posible porque las cadenas son inmutables y, por lo tanto, se pueden compartir sin problemas. el manejo compartido de "asdf" es una implementación del patrón de diseño 'Flyweight'. –

6

Es un atajo. Originalmente no era así, pero Java lo cambió.

Esto FAQ habla de ello brevemente. La guía de especificaciones de Java también lo menciona. Pero no puedo encontrarlo en línea.

+2

Enlace roto, y no tengo conocimiento de ninguna otra evidencia de que haya sido cambiado alguna vez. – EJP

+1

@EJP Todavía está en la [máquina de retorno] (http://web.archive.org/web/20130423122845/http://www.codestyle.org/java/faq-Strings.shtml#stringconstructor) si eso es útil. – Arjan

0

Siéntase libre para crear una nueva cadena con

String s = new String("I'm a new String"); 

La notación habitual s = "new String"; es más o menos un cómodo acceso directo - que debe ser usado por razones de rendimiento, excepto para aquellos casos muy raros, en las que realmente necesitará cadenas que califican para la ecuación

(string1.equals(string2)) && !(string1 == string2) 

EDITAR

En respuesta al comentario: esto fue no destinado a ser un consejo, sino solo una respuesta directa a la tesis de cuestionarios, que no usamos la palabra clave 'nueva' para cadenas, que simplemente no es t cierto Espero que esta edición (incluida la anterior) aclare esto un poco. Por cierto, hay un par de respuestas buenas y mucho mejores a la pregunta anterior sobre SO.

+4

-1 - Un mal consejo. NO debe "sentirse libre" de usar 'new String (...)' A MENOS QUE su aplicación REQUIERE que cree una Cadena con una identidad distinta. –

+1

Lo sé. Editó la publicación para aclaración. –

6

La cadena está sujeta a un par de optimizaciones (a falta de una frase mejor). Tenga en cuenta que String también tiene sobrecarga del operador (para el operador +), a diferencia de otros objetos. Entonces es un caso especial.

+1

El + es en realidad un operador que se traduce en una llamada StringBuilder.append (..). – whiskeysierra

0

Azúcar sintáctico. El

String s = new String("ABC"); 

la sintaxis todavía está disponible.

+1

Esto no es del todo correcto. s = new String ("ABC") no le dará los mismos resultados que s = "ABC". Ver el comentario de Danben. –

+2

Además, irónicamente, primero creará una instancia de Cadena que represente "ABC" en línea, y luego la pase como un argumento a la llamada del constructor que creará una cadena de retorno de idéntico valor. –

+1

El caso de uso válido para este constructor es 'String small = new String (huge.substring (int, int));', que le permite reciclar el gran subyacente 'char []' de la cadena 'huge' original. –

0

Todavía puede usar new String("string"), pero sería más difícil crear cadenas nuevas sin cadenas literales ... tendría que usar matrices de caracteres o bytes :-) Los literales de cadenas tienen una propiedad adicional: todos los mismos literales de cadenas de cualquier punto de clase a la misma instancia de cadena (están internados).

26

Las cadenas son objetos "especiales" en Java. Los diseñadores de Java sabiamente decidieron que las cadenas se utilizan tan a menudo que necesitaban su propia sintaxis y una estrategia de almacenamiento en caché. Cuando se declara una cadena diciendo:

String myString = "something"; 

miCadena es una referencia al objeto de cadena con un valor de "algo". Si más adelante declara:

String myOtherString = "something"; 

Java es lo suficientemente inteligente para saber que miCadena y myOtherString son los mismos y se almacenarlas en una tabla de cadenas global como el mismo objeto. Se basa en el hecho de que no puede modificar cadenas para hacer esto. Esto reduce la cantidad de memoria requerida y puede hacer comparaciones más rápido.

Si, en cambio, se escribe

String myOtherString = new String("something"); 

Java creará un nuevo objeto de marca para usted, distinto del objeto miCadena.

+0

Oye ... no requiere "sabiduría infinita" para reconocer la necesidad de algún tipo de soporte sintáctico para literales de cadena. Casi todos los demás diseños serios de lenguaje de programación admiten algún tipo de cadena literal. –

+10

La hipérbole se ha reducido a aturdimiento, Capitán :) –

1

En Java, las cadenas son un caso especial, con muchas reglas que se aplican solo a cadenas. Las comillas dobles hacen que el compilador cree un objeto String. Dado que los objetos String son inmutables, esto permite que el compilador interne múltiples cadenas y construya un grupo de cadenas más grande. Dos constantes de cadena idénticas siempre tendrán la misma referencia de objeto. Si no desea que sea el caso, puede usar una cadena nueva ("") y creará un objeto String en el tiempo de ejecución. El método interno() solía ser común, para hacer que las cadenas creadas dinámicamente se verifiquen con la tabla de búsqueda de cadenas. Una vez que una cadena está interna, la referencia del objeto apuntará a la instancia de cadena canónica.

String a = "foo"; 
    String b = "foo"; 
    System.out.println(a == b); // true 
    String c = new String(a); 
    System.out.println(a == c); // false 
    c = c.intern(); 
    System.out.println(a == c); // true 

Cuando el cargador de clases carga una clase, todas las constantes de cadena se agregan al grupo de cadenas.

0

Casi no hay necesidad de una cadena nueva ya que el literal (los caracteres entre comillas) ya es un objeto String creado cuando se carga la clase de host. Es perfectamente legal invocar métodos en un literal y don, la distinción principal es la conveniencia proporcionada por los literales. Sería un gran dolor y una pérdida de tiempo si tuviéramos que crear una serie de caracteres y rellenarlos por char y ellos haciendo una nueva cadena (matriz de caracteres).

0

El grupo literal contiene cadenas que se crearon sin utilizar la palabra clave new.

Existe una diferencia: la cadena sin referencia nueva se almacena en el grupo de cadenas String y String con las nuevas dice que están en la memoria del montón.

Cadena con nuevo están en otro lugar en la memoria al igual que cualquier otro objeto.

14
String a = "abc"; // 1 Object: "abc" added to pool 

String b = "abc"; // 0 Object: because it is already in the pool 

String c = new String("abc"); // 1 Object 

String d = new String("def"); // 1 Object + "def" is added to the Pool 

String e = d.intern(); // (e==d) is "false" because e refers to the String in pool 

String f = e.intern(); // (f==e) is "true" 

//Total Objects: 4 ("abc", c, d, "def"). 

Espero que esto despeje algunas dudas. :)

+0

Cadena d = nueva Cadena ("def"); // 1 Objeto + "def" se agrega al grupo -> aquí "def" se agregará al grupo solo si aún no está allí – southerton

+0

@southerton Meaningless. Ya está en el grupo. Fue colocado allí por el compilador. – EJP

+0

¡Finalmente, algo claro e informativo! – Satyam

0

Porque String es una clase inmutable en java.

¿Por qué es inmutable? Como String es inmutable, se puede compartir entre varios subprocesos y no es necesario sincronizar el funcionamiento de String externamente. As String también se utiliza en el mecanismo de carga de clase. Así que si la cadena era mutable continuación java.io.writer podría haber sido cambiado a abc.xyz.mywriter

0
TString obj1 = new TString("Jan Peter");     
TString obj2 = new TString("Jan Peter");      

if (obj1.Name == obj2.Name)     
    System.out.println("True"); 
else     
    System.out.println("False"); 

Salida:

verdadera

creé dos objetos separados, ambos tener un campo (ref) 'Nombre'. Así que incluso en este caso, "Jan Peter" se comparte, si entiendo la forma en que se negocia java ...

Cuestiones relacionadas