2012-12-10 14 views
13

Eventuali duplicati:
What is the purpose of the expression “new String(…)” in Java?Perché la classe String ha un costruttore di copie?

Se le classi immutabili oggetti copie sarebbero uguali agli originali allora perché la classe String in Java hanno un costruttore di copia? È un errore o c'è una ragione dietro questa implementazione? nella documentazione Java si precisa che:

/** 
* Initializes a newly created {@code String} object so that it represents 
* the same sequence of characters as the argument; in other words, the 
* newly created string is a copy of the argument string. Unless an 
* explicit copy of {@code original} is needed, use of this constructor is 
* unnecessary since Strings are immutable. 
* 
* @param original 
*   A {@code String} 
*/ 
public String(String original) { 
.... 
....} 
+6

Questo non è "troppo localizzato", è una buona domanda applicabile a coloro che lo trovano più tardi, con una risposta molto utile e informativa. –

+3

Vedere [questo] (http://stackoverflow.com/a/465682/1037210) risposta. – Lion

+0

Si noti che le risposte alla domanda simile citata possono probabilmente essere considerate parzialmente obsolete. –

risposta

10

Il motivo principale per copiare una stringa è "tagliare il bagaglio", cioè per tagliare il sottostante matrice char solo quanto necessario.

Il char array sottostante può essere principalmente troppo grande perché quando si crea una stringa chiamando substring, il char array può essere condiviso tra la nuova istanza della stringa e l'istanza della stringa di origine; un offset punta al primo carattere e la lunghezza è inclusa.

L'espressione che uso, "tagliare il bagaglio", è presa dal codice sorgente di stringa costruttore di copia:

164  public String(String original) { 
    165   int size = original.count; 
    166   char[] originalValue = original.value; 
    167   char[] v; 
    168   if (originalValue.length > size) { 
    169    // The array representing the String is bigger than the new 
    170    // String itself. Perhaps this constructor is being called 
    171    // in order to trim the baggage, so make a copy of the array. 
    172    int off = original.offset; 
    173    v = Arrays.copyOfRange(originalValue, off, off+size); 
    174   } else { 
    175    // The array representing the String is the same 
    176    // size as the String, so no point in making a copy. 
    177    v = originalValue; 
    178   } 
    179   this.offset = 0; 
    180   this.count = size; 
    181   this.value = v; 

Questo è qualcosa che molti sviluppatori dimenticano ed è importante perché una piccola stringa può prevenire il garbaging di un array di caratteri più grande. Vedi questa domanda correlata in cui ho già sottolineato questo: Java not garbage collecting memory. Molti sviluppatori considerano che la decisione dei progettisti Java di utilizzare questo vecchio trucco di ottimizzazione che era familiare ai programmatori C, in effetti, faceva più male che bene. Molti di noi lo sanno perché siamo stati morsi e abbiamo dovuto esaminare il codice sorgente di Sun per capire cosa è successo ...

Come sottolinea Marko (vedere i commenti sotto), in OpenJDK, a partire da java 7 Update 6 , substring non condivide più il char array e il costruttore String(String) è, quindi, inutile. Ma è ancora veloce (anzi è più veloce di fatto) e poiché questa modifica non è stata propagata a tutte le VM (e probabilmente non a tutti i tuoi clienti) ti consiglio di mantenere questa best practice per usare new String(substring) quando il vecchio comportamento lo giustificava .

+5

... e se ne è andato a partire da OpenJDK 7, Aggiornamento 6. Non c'è più condivisione strutturale attraverso 'sottostringhe',' trim' ecc. –

+0

@Marko Puoi indicare la fonte dell'aggiornamento che hai citato? Non ero a conoscenza di questo importante cambiamento. –

+3

[Riferimento qui] (http://hg.openjdk.java.net/jdk7u/jdk7u6/jdk/file/8c2c5d63a17e/src/share/classes/java/lang/String.java) L'ho già messo tra i segnalibri, è è stato molto richiesto da quando ho saputo da Jon Skeet a riguardo! –

Problemi correlati