Pregunta

¿Por qué es java.lang.String la única clase para la que existen dos formas de creación:

1) Con la forma normal con " nuevo " palabra clave.

String s = new String("abc");

2) Con String literal (que solo está disponible con la clase String )

String s = "abc";

Entonces, ¿por qué hay String literales y no literales para otras clases?

¿Fue útil?

Solución

La cadena, aunque es una clase normal, representa uno de los elementos básicos de la programación (los otros son números y valores booleanos). Por lo tanto, Java ha considerado los objetos String como variables semi-primitivas desde el primer día, y ha permitido esto.

Más adelante, cuando el boxeo automático se convirtió en parte del compilador estándar, también podría crear objetos envoltorios numéricos de esta manera, es decir,

Integer i = 123;

como lo menciona Tom Hawtin-tackline en los comentarios a la pregunta.

Otros consejos

Respuesta corta, porque a los diseñadores de idiomas les dio la gana.

Supongo que String es una clase tan común que hicieron una excepción. Estoy seguro de que también hay otras excepciones similares (vea el comentario de Tom Hawtins)

Dejando de lado el autoboxing (que no cuenta IMO - los literales son para los tipos primitivos en lugar de las clases; solo hay una conversión implícita a la clase envoltura), el constructor String (String) es realmente útil Toma una copia de los datos de caracteres, lo que significa que si la cadena original es pequeña pero con un gran respaldo char [] , la nueva cadena es independiente de ella.

Esto puede ser importante si estás leyendo líneas cortas de un archivo, por ejemplo.

En cuanto a por qué hay literales de cadena: porque son útiles. ¿Qué tendrías en su lugar? ¿Te gustaría forzar a los desarrolladores a usar:

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

¿Y al mismo tiempo no realizar una pasantía?

¿Para qué otra clase quieres un literal? Podría decirse que los literales para mapas y listas serían útiles, no puedo recordar si vienen en Java 7 o no. Puede pensar en los inicializadores de matriz como " un poco como un literal " en eso es una abreviatura para la inicialización de objetos.

Supongo que debido a que String es un tipo de datos fundamental, lo consideran al mismo nivel que los primitivos.

Por cierto,

new String("abc");

en realidad crea 2 cadenas:

  1. el internado, del cual pierdes la referencia
  2. una nueva instancia con el mismo contenido

Personalmente, nunca he encontrado la necesidad de usar el constructor de String.

Los tipos de objetos que tienen literales son Cadenas , null y literales de clase .

También es posible usar inicializadores para arrays y los literales primitivos también se pueden usar para crear objetos si se usan como inicializadores, que se ajustan a las "dos formas de creación" en sintaxis simple sin ser literales verdaderos (solo pueden usarse para inicializar un valor en lugar de en todos los lugares donde puede ocurrir una expresión de objeto).

Si utiliza otras técnicas como la serialización y la reflexión, puede romper las " dos formas de creación " también.

Java 7 está programado para proporcionar la capacidad de recopilar colecciones iniciales a través de literales de manera muy similar a los literales de matriz:

La última vez que verifiqué:

Integer wInt = 1;

Funciona bien.

La última forma de creación también implica el internado de cadenas. Es decir, si tiene el código:

String s = "abc";
String t = "abc";

el compilador optimizará esto y obtendrás dos referencias al mismo objeto String. (s == t será cierto).

La internación de cadenas también funciona para las expresiones de cadenas.

Por supuesto, también hay literales para todos los tipos numéricos primitivos, y los booleanos verdadero y falso, y caracteres. Supongo que podría responder que en su pregunta técnicamente dijo "no literales para ninguna otra clase " ;. Bueno. Creo que alguien señaló que " null " es un objeto literal, por lo que su declaración es técnicamente inexacta, pero creo que ese es el único otro ejemplo.

Pero entonces, la siguiente pregunta obvia es: ¿para qué otras clases querrías tener literales? Si estuvieras diseñando el lenguaje, ¿cómo sería un literal de BufferedReader? ¿O un literal ResultSet? ¿O un JCheckBox?

Teóricamente podría decir que, por ejemplo, un " Archivo literal " es el nombre del archivo incluido en algún delimitador especial, como " $ / home / bob / myfile.txt $ " Pero alguien podría decir: ¿Qué pasa con un JButton? Y luego, ¿qué pasa con Sockets? ¿No podríamos poner el nombre del host en algún delimitador especial? Creo que está bastante claro que pronto nos quedaremos sin signos de puntuación para usarlos como delimitadores. Así que tendríamos que escribir algún tipo de texto para identificar de qué clase hablamos, como decir Archivo (" /home/bob/myfile.txt") o Socket (" www.example.com " , 631). Pero se parece mucho a un constructor, y volveríamos a lo que realmente hicieron los autores de Java.

El número de " cosas " eso puede expresarse simplemente por la naturaleza del valor (por ejemplo, todos los dígitos forman un literal numérico) o la puntuación está bastante limitada por el número de signos de puntuación que pueden caber razonablemente en un teclado. ¿Y desearía un teclado con 600 íconos especiales para todos los diferentes tipos de cosas de las que quizás quiera hablar? Las palabras son mucho más fáciles y más flexibles.

La cadena se usa con tanta frecuencia, y las alternativas hubieran sido tan incómodas, que hubiera tenido sentido convertirla en un caso especial.

Los literales de cadena son un atajo conveniente con una precedencia bien establecida (en C) y sintaxis. Si los diseñadores de Java querían atraer a los programadores de C ++, los literales de cadena debían estar allí. Afortunadamente, el manejo de cadenas es mucho más sensato en Java que en C ++.

Ningún otro objeto estándar tenía una sintaxis de facto: ¿cómo escribirías un literal de mapa?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top