Domanda

Perché java.lang.String è l'unica classe per la quale esistono due modi di creare:

1) In modo normale con " nuovo " parola chiave.

String s = new String("abc");

2) Con String letterale (che è disponibile solo con la classe String )

String s = "abc";

Allora perché ci sono letterali String e nessun letterale per altre classi ??

È stato utile?

Soluzione

La stringa, pur essendo una classe ordinaria, rappresenta uno degli elementi base della programmazione (gli altri sono numeri e valori booleani). Pertanto, Java ha considerato gli oggetti String come variabili semi-primitive dal primo giorno e lo ha permesso.

In seguito, quando l'auto-boxing è diventato parte del compilatore standard, è anche possibile creare oggetti wrapper numerici in questo modo, ad esempio

Integer i = 123;

come menziona Tom Hawtin-tackline nei commenti alla domanda.

Altri suggerimenti

Risposta breve, perché i progettisti del linguaggio ne avevano voglia.

Suppongo che String sia una classe così comune che hanno fatto un'eccezione. Sono sicuro che ci sono anche altre eccezioni simili (vedi il commento di Tom Hawtins)

Lasciando da parte l'autoboxing (che non conta IMO - i valori letterali sono per i tipi primitivi piuttosto che per le classi; c'è solo una conversione implicita nella classe wrapper), il costruttore String (String) è effettivamente utile. Prende una copia dei dati del carattere, il che significa che se la stringa originale è piccola ma con un supporto char [] di grandi dimensioni, la nuova stringa è indipendente da essa.

Questo può essere importante se stai leggendo brevi righe da un file, ad esempio.

Per quanto riguarda il motivo per cui ci sono letterali stringa: perché sono utili. Cosa avresti invece? Vorresti forzare gli sviluppatori a usare:

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

e allo stesso tempo non ottenere interning?

Per quale altra classe vorresti un letterale? Probabilmente i letterali per mappe ed elenchi sarebbero utili: non ricordo se arrivano in Java 7 o no. Puoi pensare agli inizializzatori di array come "un po 'come un letterale" in quanto è una scorciatoia per l'inizializzazione dell'oggetto.

Suppongo che String sia un tipo di dati fondamentale che lo considerano allo stesso livello delle primitive.

A proposito,

new String("abc");

attualmente crea 2 stringhe:

  1. quello internato, di cui perdi il riferimento
  2. una nuova istanza con lo stesso contenuto

Personalmente, non ho mai trovato il bisogno di usare il costruttore di String.

I tipi di oggetto che hanno valori letterali sono Stringhe , null e letterali di classe .

È anche possibile utilizzare gli inizializzatori per array e i letterali primitivi possono anche essere usati per creare oggetti se usati come inizializzatori, che si adattano alle "due modalità di creazione" in una sintassi semplice senza essere veri letterali (possono essere utilizzati solo per inizializzare un valore anziché in tutti i punti in cui può verificarsi un'espressione di un oggetto).

Se utilizzi altre tecniche come la serializzazione e la riflessione, puoi interrompere le "due modalità di creazione" anche.

Java 7 è previsto per fornire la possibilità di inizializzare raccolte tramite valori letterali molto simili ai valori letterali dell'array:

Ultimo controllo:

Integer wInt = 1;

Funziona bene.

Quest'ultima forma di creazione prevede anche l'internamento di stringhe. Cioè, se hai il codice:

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

il compilatore ottimizzerà questo e otterrai due riferimenti allo stesso oggetto String. (s == t sarà vero).

Lo string interning funziona anche per le espressioni di stringa.

Ci sono, ovviamente, anche valori letterali per tutti i tipi numerici primitivi, i booleani vero e falso e i caratteri. Suppongo che potresti rispondere che nella tua domanda tecnicamente hai detto "niente letterali per altre classi ". Va bene. Penso che qualcuno abbia sottolineato che " null " è un oggetto letterale, quindi la tua affermazione è tecnicamente inaccurata, ma penso che sia l'unico altro esempio.

Ma poi, la prossima domanda ovvia è: per quali altre classi vorresti avere dei letterali? Se si stesse progettando la lingua, come sarebbe un letterale BufferedReader? O un ResultSet letterale? O un JCheckBox?

Teoricamente potresti dire che, ad esempio, un file " letterale " è il nome del file racchiuso in alcuni delimitatori speciali, come " $ / home / bob / myfile.txt $ " ;. Ma poi qualcuno potrebbe dire: che dire di un JButton, non potremmo fare un letterale per quel tipo con il testo del pulsante e l'ActionListener che genera e delimitatori appropriati, come "% Submit, SubmitListener% " ;. E poi per quanto riguarda Socket, non possiamo inserire il nome host in un delimitatore speciale, ecc. Penso che sia abbastanza chiaro che saremmo rapidamente a corto di segni di punteggiatura da usare come delimitatori. Quindi finiremmo per scrivere una sorta di testo per identificare di quale classe stiamo parlando, come dire File (" /home/bob/myfile.txt") o Socket (" www.example.com " , 631). Ma assomiglia moltissimo a un costruttore, e torneremmo subito a quello che hanno fatto gli autori di Java.

Il numero di " cose " che può essere espresso semplicemente dalla natura del valore (ad es. tutte le cifre rendono letterale un numero) o con la punteggiatura è piuttosto limitata dal numero di segni di punteggiatura che possono essere ragionevolmente adattati a una tastiera. E vorresti una tastiera con 600 icone speciali per tutti i diversi tipi di cose di cui potresti voler parlare? Le parole sono molto più semplici e flessibili.

La stringa è così comunemente usata e le alternative sarebbero state così imbarazzanti, che aveva senso trasformarla in un caso speciale.

I letterali stringa sono una scorciatoia conveniente con una precedenza ben definita (in C) e sintassi. Se i progettisti Java volevano attirare i programmatori C ++, i letterali delle stringhe dovevano essere lì. Fortunatamente la gestione delle stringhe è molto più sana in Java che in C ++.

Nessun altro oggetto standard aveva una sintassi di fatto: come scriveresti una mappa letterale?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top