Perché String è immutabile in Java?

Mi è stato chiesto in un’intervista perché String sia immutabile

Ho risposto così:

Quando creiamo una stringa in java come String s1="hello"; quindi un object verrà creato nel pool di stringhe (ciao) e s1 indicherà ciao . Ora se ancora facciamo String s2="hello"; quindi un altro object non verrà creato ma s2 punterà su hello perché JVM verificherà prima se lo stesso object è presente nel pool di string oppure no. Se non è presente, ne verrà creato solo uno nuovo.

Ora se supponiamo che java consenta la stringa mutabile, se cambiamo s1 in hello world allora anche il valore s2 sarà hello world quindi java String è immutabile.

Qualcuno può dirmi se la mia risposta è giusta o sbagliata ?

String è immutabile per diversi motivi, ecco un riassunto:

  • Sicurezza : i parametri sono tipicamente rappresentati come String nelle connessioni di rete, url di connessione al database, nomi utente / password ecc. Se fosse mutabile, questi parametri potrebbero essere facilmente modificati.
  • Sincronizzazione e simultaneità: la creazione di String immutable li rende automaticamente thread-safe, risolvendo così i problemi di sincronizzazione.
  • Memorizzazione nella cache : quando il compilatore ottimizza gli oggetti String, vede che se due oggetti hanno lo stesso valore (a = “test” e b = “test”) e quindi è necessario un solo object stringa (per entrambi aeb, questi due puntare allo stesso object).
  • Caricamento della class : la String viene utilizzata come argomento per il caricamento della class. Se mutabile, potrebbe causare il caricamento di una class errata (perché gli oggetti mutabili cambiano il loro stato).

Detto questo, l’immutabilità di String significa solo che non puoi cambiarlo usando la sua API pubblica. In effetti puoi bypassare la normale API usando la reflection. Vedi la risposta qui .

Nel tuo esempio, se String era mutabile, prendi in considerazione il seguente esempio:

  String a="stack"; System.out.println(a);//prints stack a.setValue("overflow"); System.out.println(a);//if mutable it would print overflow 

Gli sviluppatori Java decidono che le stringhe sono immutabili a causa del seguente aspetto , efficienza e sicurezza .

Le stringhe di progettazione vengono create in un’area di memoria speciale nell’heap java noto come “String Intern pool”. Durante la creazione di una nuova stringa (non nel caso di utilizzo del costruttore String () o di altre funzioni String che utilizzano internamente il costruttore String () per creare un nuovo object String; il costruttore String () crea sempre una nuova costante di stringa nel pool a meno che chiama la variabile metodo intern () ) che cerca nel pool per verificare se è già esistente. Se esiste, quindi restituisce il riferimento dell’object String esistente. Se la stringa non è immutabile, la modifica della stringa con un riferimento determinerà il valore errato per gli altri riferimenti.

Secondo questo articolo su DZone:

La stringa di sicurezza è ampiamente utilizzata come parametro per molte classi java, ad esempio la connessione di rete, i file di apertura, ecc. Se la stringa non è immutabile, una connessione o un file potrebbero essere modificati e causare gravi minacce alla sicurezza. Anche le stringhe mutabili possono causare problemi di sicurezza in Reflection, poiché i parametri sono stringhe.

Efficienza Il codice hash della stringa viene spesso utilizzato in Java. Ad esempio, in una HashMap. Essere immutabili garantisce che hashcode sarà sempre lo stesso, in modo che possa essere memorizzato nella cache senza preoccuparsi delle modifiche. Ciò significa che non è necessario calcolare hashcode ogni volta che viene utilizzato.

Motivo più importante in base a questo articolo su DZone:

String Costante Pool … Se la stringa è mutabile, cambiare la stringa con un riferimento porterà al valore sbagliato per gli altri riferimenti.

Sicurezza

La stringa è ampiamente utilizzata come parametro per molte classi java, ad esempio la connessione di rete, i file di apertura, ecc. Se la stringa non è immutabile, una connessione o un file verrebbero modificati e porterebbero a gravi minacce alla sicurezza. …

Spero ti possa aiutare.

Non possiamo essere sicuri di cosa stessero pensando i progettisti Java durante la progettazione di String ma possiamo solo concludere questi motivi in ​​base ai vantaggi che derivano dall’immutabilità delle stringhe, alcuni dei quali sono

1. Esistenza di un pool costante di stringhe

Come discusso in Why String è memorizzato in un articolo Costante di Cost string , ogni applicazione crea troppi oggetti stringa e per salvare JVM crea innanzitutto molti oggetti stringa e quindi li raccoglie. JVM memorizza tutti gli oggetti stringa in un’area di memoria separata denominata pool di costanti stringa e riutilizza oggetti da quel pool memorizzato nella cache.

Ogni volta che creiamo una stringa JVM letterale, prima vediamo se quel letterale è già presente nel pool costante o no e se è presente, il nuovo riferimento inizierà a puntare allo stesso object in SCP.

 String a = "Naresh"; String b = "Naresh"; String c = "Naresh"; 

Nell’esempio precedente, l’object stringa con valore Naresh verrà creato in SCP solo una volta e tutti i riferimenti a , b , c a.replace("a", "") allo stesso object ma cosa a.replace("a", "") a modificare in es a.replace("a", "") .

Idealmente, a valore dovrebbe avere Nresh ma b , c dovrebbe rimanere invariato perché come utente finale stiamo apportando il cambiamento in a solo. E sappiamo a , b , c tutti puntano lo stesso object quindi se facciamo un cambiamento in a , gli altri dovrebbero anche riflettere il cambiamento.

Ma l’immutabilità delle stringhe ci salva da questo scenario e, a causa dell’immutabilità dell’object stringa stringa, Naresh non cambierà mai. Quindi, quando apportiamo qualche modifica in a anziché in a object stringa, Naresh JVM crea un nuovo object assegnandolo a a e quindi apportando modifiche in quell’object.

Quindi, il pool di stringhe è ansible solo a causa dell’immutabilità di String e se String non sarebbe stato immutabile, quindi la memorizzazione nella cache di oggetti stringa e il loro riutilizzo non avrebbero alcuna possibilità, poiché qualsiasi variabile avrebbe modificato il valore e danneggiato altri.

Ed è per questo che è gestito da JVM in modo molto speciale e gli è stata assegnata una speciale area di memoria.

2. Sicurezza del filo

Un object si chiama thread-safe quando su di esso operano più thread, ma nessuno di essi è in grado di alterarne lo stato e l’object mantiene lo stesso stato per ogni thread in qualsiasi momento.

Come noi, un object immutabile non può essere modificato da nessuno dopo la sua creazione, il che rende ogni object immutabile sicuro per impostazione predefinita. Non è necessario applicare alcuna misura di sicurezza del thread ad esso come la creazione di metodi sincronizzati.

Quindi, a causa della sua natura immutabile, l’object stringa può essere condiviso da più thread e anche se viene manipolato da molti thread non ne modifica il valore.

3. Sicurezza

In ogni applicazione, è necessario passare diversi segreti, ad esempio nome utente utente \ password, URL di connessione e in generale, tutte queste informazioni vengono passate come object stringa.

Ora supponiamo che String non sarebbe stato immutabile in natura, quindi causerebbe una seria minaccia alla sicurezza dell’applicazione perché questi valori possono essere modificati e se è consentito, questi potrebbero essere cambiati a causa di codice scritto erroneamente o di qualsiasi altra persona che avere accesso ai nostri riferimenti variabili.

4. Caricamento della class

Come discusso in Creazione di oggetti tramite Reflection in Java con Example , possiamo usare il Class.forName("class_name") per caricare una class in memoria che richiama ancora altri metodi per farlo. E anche JVM usa questi metodi per caricare le classi.

Ma se vedi chiaramente tutti questi metodi accetta il nome della class come object stringa in modo che le stringhe vengano utilizzate nel caricamento della class java e l’immutabilità fornisca la sicurezza che la class corretta viene caricata da ClassLoader .

Supponiamo che String non sia immutabile e stiamo provando a caricare java.lang.Object che viene cambiato in org.theft.OurObject tra e ora tutti gli oggetti hanno un comportamento che qualcuno può usare per cose indesiderate.

5. Cache HashCode

Se eseguiremo operazioni correlate all’hashing su qualsiasi object, dobbiamo sovrascrivere il metodo hashCode() e provare a generare un hashcode accurato utilizzando lo stato dell’object. Se lo stato dell’object viene modificato, significa che anche il codice hash dovrebbe cambiare.

Poiché String è immutabile, il valore dell’object stringa non viene mai modificato, il che significa che anche l’hashcode non cambierà il che conferisce alla class String l’opportunità di memorizzare il codice hash durante la creazione dell’object.

Sì, l’object String memorizza nella cache il suo codice hash al momento della creazione dell’object, il che lo rende il candidato ideale per le operazioni correlate all’hashing perché non è necessario calcolare nuovamente hashcode, il che ci fa risparmiare un po ‘di tempo. Questo è il motivo per cui String viene utilizzato principalmente come chiavi HashMap .

Maggiori informazioni su Why String è Immutable e Final in Java .

Ho letto questo post Perché String è Immutable o Final in Java e supponiamo che la seguente possa essere la ragione più importante:

String è immutabile in Java perché gli oggetti stringa sono memorizzati nella cache nel pool di stringhe . Poiché i valori letterali delle stringhe memorizzati nella cache sono condivisi tra più client, esiste sempre un rischio, in cui l’azione di un client influisce su tutti gli altri client.

La stringa è immutabile perché: –

1. Progettazione: – Il pool di stringhe è ansible solo perché String è immutabile in java, in questo modo Java Runtime salva molto spazio java heap perché le variabili String diverse possono fare riferimento alla stessa variabile String nel pool. Se String non fosse immutabile, l’interning delle stringhe non sarebbe stato ansible perché se qualche variabile avrebbe modificato il valore, sarebbe stato riflesso anche in altre variabili.

2. Sicurezza: – Se String non è immutabile, causerebbe gravi minacce alla sicurezza per l’applicazione. Ad esempio, il nome utente del database, la password vengono passati come String per ottenere la connessione al database e nell’host di programmazione socket e i dettagli della porta passati come String. Poiché String è immutabile, il suo valore non può essere modificato, altrimenti qualsiasi hacker potrebbe modificare il valore di riferimento per causare problemi di sicurezza nell’applicazione.

3. Discussione sicura: – Poiché String è immutabile, è sicuro per il multithreading e una singola istanza String può essere condivisa tra diversi thread. Questo evita l’uso della sincronizzazione per la sicurezza dei thread, le stringhe sono implicitamente thread-safe

4. classloader: – Le stringhe sono usate in java classloader e l’immutabilità fornisce sicurezza che la class corretta viene caricata da Classloader. Ad esempio, pensa a un’istanza in cui stai tentando di caricare la class java.sql.Connection ma il valore di riferimento viene modificato nella class myhacked.Connection che può eseguire operazioni indesiderate sul tuo database.

5. Caching: – Poiché String è immutabile, il suo hashcode è memorizzato nella cache al momento della creazione e non è necessario che venga calcolato nuovamente. Ciò lo rende un ottimo candidato per la chiave in una mappa e la sua elaborazione è veloce rispetto ad altri oggetti chiave HashMap. Questo è il motivo per cui String viene utilizzato principalmente come chiavi HashMap. Sopra sono alcune delle ragioni per cui potrei pensare che mostra i benefici dell’immutabilità di String. È una grande funzionalità della class String di Java e lo rende speciale.

Hai ragione. String in java utilizza il concetto di String Pool di String Pool letterale. Quando viene creata una stringa e se la stringa esiste già nel pool, verrà restituito il riferimento della stringa esistente, invece di creare un nuovo object e restituirne il riferimento. Se una stringa non è immutabile, la modifica della stringa con un riferimento sarà portare al valore sbagliato per gli altri riferimenti.

Vorrei aggiungere ancora una cosa, dal momento che String è immutabile, è sicuro per il multi-threading e una singola istanza String può essere condivisa tra diversi thread. Questo evita l’uso della sincronizzazione per la sicurezza dei thread, le stringhe sono implicitamente thread safe .

La class di stringhe è FINAL significa che non puoi creare alcuna class per ereditarla e modificare la struttura di base e rendere mutevole la Sting.

Un’altra variabile di istanza cosa e i metodi della class String forniti sono tali che non è ansible modificare l’object String una volta creato.

Il motivo per cui ciò che hai aggiunto non rende affatto immutabile la stringa. Tutto questo dice che la stringa è archiviata nell’heap. Anche il pool di stringhe fa l’enorme differenza nelle prestazioni

La stringa è data come immutabile dai sistemi micro di Sun, perché la stringa può essere utilizzata come chiave nella raccolta di mappe. StringBuffer è mutabile. Questo è il motivo, non può essere usato come chiave nell’object mappa

La ragione più importante per cui una stringa viene resa immutabile in Java è la considerazione della sicurezza . Il prossimo sarebbe Caching .

Credo che altre ragioni date qui, come l’efficienza, la concorrenza, il design e il pool di stringhe derivino dal fatto che String sia reso immutabile. Per es. È ansible creare un pool di stringhe perché String era immutabile e non viceversa.

Controlla la trascrizione dell’intervista di Gosling qui

Da un punto di vista strategico, tendono a essere più spesso senza problemi. E di solito ci sono cose che puoi fare con immutables che non puoi fare con cose mutevoli, come il risultato della cache. Se si passa una stringa a un metodo di apertura file o se si passa una stringa a un costruttore per un’etichetta in un’interfaccia utente, in alcune API (come in molte API di Windows) si passa in una matrice di caratteri. Il ricevitore di quell’object deve davvero copiarlo, perché non sanno nulla della durata di memorizzazione di esso. E non sanno cosa sta succedendo all’object, se viene cambiato sotto i loro piedi.

Finisci per essere quasi costretto a replicare l’object perché non sai se lo possiedi o no. E una delle cose belle degli oggetti immutabili è che la risposta è “Sì, certo che lo fai”. Perché la questione della proprietà, chi ha il diritto di cambiarla, non esiste.

Una delle cose che obbligava le stringhe a essere immutabili era la sicurezza. Hai un metodo di apertura file. Passi una stringa ad esso. E poi sta facendo tutti i tipi di controlli di autenticazione prima che faccia il giro della chiamata al SO. Se riesci a fare qualcosa che ha effettivamente modificato la stringa, dopo il controllo di sicurezza e prima della chiamata del sistema operativo, quindi boom, sei dentro. Ma le stringhe sono immutabili, quindi quel tipo di attacco non funziona. Questo preciso esempio è ciò che realmente richiedeva che le stringhe fossero immutabili

Oltre alle grandi risposte, ho voluto aggiungere alcuni punti. Come le stringhe, Array contiene un riferimento all’avvio dell’array, quindi se crei due array arr1 e arr1 e arr2 qualcosa come arr2 = arr1 questo renderà il riferimento di arr2 stesso di arr1 cambiando il valore in uno di essi si otterrà un cambiamento dell’altro per esempio

 public class Main { public static void main(String[] args) { int[] a = {1, 2, 3, 4}; int[] b = a; a[0] = 8; b[1] = 7; System.out.println("A: " + a[0] + ", B: " + b[0]); System.out.println("A: " + a[1] + ", B: " + b[1]); //outputs //A: 8, B: 8 //A: 7, B: 7 } } 

Non solo ciò causerebbe errori nel codice, ma può anche essere sfruttato dall’utente malintenzionato. Supponiamo che tu abbia un sistema che modifica la password dell’amministratore. L’utente deve prima inserire la newPassword e poi la oldPassword se la oldPassword è la stessa di adminPass il programma cambia la password da adminPass = newPassword . diciamo che la nuova password ha lo stesso riferimento della password dell’amministratore, quindi un programmatore malvagio potrebbe creare una variabile temp per contenere la password oldPassword prima che gli utenti oldPassword i dati se la oldPassword è uguale a temp cambia la password altrimenti adminPass = temp . Qualcuno sa che potrebbe facilmente inserire la nuova password e non inserire mai la vecchia password e abracadabra che ha accesso come amministratore. Un’altra cosa che non ho capito quando ho imparato a conoscere le stringhe, perché JVM non crea una nuova stringa per ogni object e ha un posto unico in memoria per questo e puoi farlo usando il new String("str"); La ragione per cui non si vorrebbe usare sempre new è perché non è efficiente in termini di memoria ed è più lenta nella maggior parte dei casi a leggere di più .

Se HELLO è la tua stringa, allora non puoi cambiare HELLO in HILLO . Questa proprietà è chiamata proprietà di immutabilità.

È ansible avere più variabili String del puntatore per puntare HELLO String.

Ma se CIAO è char Array, allora puoi cambiare CIAO in HILLO. Per esempio,

 char[] charArr = 'HELLO'; char[1] = 'I'; //you can do this 

Risposta:

I linguaggi di programmazione hanno variabili di dati immutabili che possono essere utilizzate come chiavi in ​​chiave, coppia di valori. Le variabili stringa vengono utilizzate come chiavi / indici, quindi sono immutabili .

Dal punto di vista della Security possiamo usare questo esempio pratico:

 DBCursor makeConnection(String IP,String PORT,String USER,String PASS,String TABLE) { // if strings were mutable IP,PORT,USER,PASS can be changed by validate function Boolean validated = validate(IP,PORT,USER,PASS); // here we are not sure if IP, PORT, USER, PASS changed or not ?? if (validated) { DBConnection conn = doConnection(IP,PORT,USER,PASS); } // rest of the code goes here .... }