2013-04-03 10 views
7

Dato il seguente codice:StringBuffer e String piscina

StringBuffer str2 = new StringBuffer(" I don't"); 
    StringBuffer str3 = str2.append(" get it."); 
    if (str2 == str3) 
    { 
     System.out.println("Equal"); 
    } 

mio professore dice, che in questo caso sia str2 e str3 si riferiscono allo stesso oggetto e la stringa "Io non capisco" volontà essere inserito nel "pool di stringhe".

Penso che capisco perché str2 e str3 faranno ora riferimento allo stesso oggetto, ma Perché la stringa "Non capisco." entrare nel pool di stringhe quando si verifica l'assegnazione str3?

Per esempio, se faccio:

String s = "abcd"; 

allora so che ora la stringa "ABCD" verrà inserito nel "pool String" se non è già lì.

Mi piacerebbe avere una spiegazione.

+1

@assylias: Sì, sarà, dal momento che 'append()' restituisce 'this'. –

+0

L'OP è chiaro sul motivo per cui i due oggetti sono uguali. La domanda è: perché la stringa "Non capisco". sarà in pool di stringhe. –

+2

E 'possibile che tu abbia frainteso il tuo istruttore, ma se per 'inserito nel" pool di stringhe "' come implicante il valore di StringBuffers sarebbe * internato *, che è *** sicuramente non corretto. – Perception

risposta

5

Perché la stringa "Non capisco." entrare nel pool di stringhe.

La stringa "I don't get it." non entra nel pool di internamento.

Un modo per verificarlo è la seguente:

StringBuffer str2 = new StringBuffer(" I don't"); 
StringBuffer str3 = str2.append(" get it."); 
String str = new String(str3.toString()); 
if (str == str.intern()) { 
    System.out.println("It was not interned before"); // <<== This is printed 
} else { 
    System.out.println("It was interned before"); 
} 

Se il contenuto String s' è internato, la chiamata di intern() restituirà un oggetto diverso ('canonica'). Come puoi vedere, quanto sopra restituisce lo stesso oggetto, il che significa che l'oggetto su cui chiami intern() diventa semplicemente "canonico" (cioè è stato internato).

D'altra parte, se si rimuove il append, si otterrebbe un risultato diverso:

StringBuffer str2 = new StringBuffer(" I don't"); 
StringBuffer str3 = str2; 
String str = new String(str3.toString()); 
if (str == str.intern()) { 
    System.out.println("It was not interned before"); // <<== This is printed 
} else { 
    System.out.println("It was interned before"); 
} 

Ora la stringa all'interno str3 è " I don't". La sua copia è già internata, perché è uguale alla costante di stringa utilizzata nella creazione dello str2.

È possibile eseguire i programmi the first e the second fianco a fianco per vedere la differenza.

Il motivo per cui str2 == str3 è true non ha nulla a che fare con i lotti di stringhe (la parola gergale è "string interning"). I due sono uguali perché StringBuffer.append restituisce l'oggetto su cui viene invocato il append, ad esempio str2. Non hai un secondo oggetto: c'è solo uno StringBuffer con due riferimenti. Il contenuto di tale StringBuffer è la concatenazione delle stringhe " I don't" e " get it.".

+1

Ok, non ha nulla a che fare con la stringa interning .. ma è vero che la stringa "I do not get it" entrerà qui? – Rouki

+2

No, la stringa "I do not get it" non sarà internata. Basta leggere l'implementazione toString() di StringBuffer, e lo confermerà. –

+0

@JBNizet Chi sta parlando di internare il '" Non capisco. "' Qui? Certo che no! – dasblinkenlight

0

Stai comparando StringBuffer oggetti, non (internato) String 's. Se date un'occhiata all'implementazione StringBuffer.append(String) noterete che finisce con return this;, quindi il vostro str2 e str3 è lo stesso oggetto.

public synchronized StringBuffer append(String str) { 
super.append(str); 
    return this; 
} 

Edit: Mentre le due stringhe letterali nel codice sono internati (nella "piscina String"), la stringa combinato "Io non capisco" non sarà internato. Questo è chiaro ispezionando il codice StringBuffer (che rappresenta la combinazione come matrice char[] internamente.)

Acclamazioni,

+0

Grazie, ma come ho detto, penso che capisco perché si riferiscono agli stessi oggetti. ma puoi dirmi perché la stringa verrà inserita nel "pool di stringhe" ora? – Rouki

+1

I letterali stringa "I do not" e "get it" saranno internati, la combinazione dei due non lo farà! Internamente 'StringBuffer' usa un array di caratteri e crea solo un' nuovo String (...) 'quando necessario, questo non implica internamento. –

0

StringBuffer#append(StringBuffer sb)

aggiunge StringBuffer specificato a questa sequenza. I caratteri di l'argomento StringBuffer vengono aggiunti, in ordine, al contenuto di questo StringBuffer, aumentando la lunghezza di questo StringBuffer per la lunghezza dell'argomento . Se sb è null, i quattro caratteri "null" vengono aggiunti a questo StringBuffer.

Sia n la lunghezza della vecchia sequenza di caratteri, quella contenuta nello StringBuffer appena prima dell'esecuzione del metodo append. Quindi il carattere nell'indice k nella nuova sequenza di caratteri è uguale al carattere all'indice k nella sequenza di caratteri precedenti, se k è minore di n; in caso contrario, è uguale al carattere nell'indice k-n nell'argomento sb.

Questo metodo si sincronizza su questo oggetto (la destinazione) ma non si sincronizza all'origine (sb).

Si otterrà vero perché il riferimento è lo stesso per entrambi.

0

Sembra esserci un po 'di confusione. StringBuffer è mutabile, il che significa che il suo contenuto può essere modificato. Il metodo append(), da StringBuffer, aggiunge una stringa alla stringa all'interno del buffer e restituisce l'istanza. Così la linea:

StringBuffer str3 = str2.append(" get it."); 

avrà lo stesso risultato pratico come:

str2.append(" get it."); 
StringBuffer str3 = str2; 

In altre parole, str3 e punto str2 allo stesso oggetto. Perché hai aggiunto il letterale String "prendilo". a "I do not", questo StringBuffer conterrà "I do not get it".

0

Perché la stringa "Non capisco." entrare nel pool di stringhe quando si verifica l'assegnazione str3?

Non funziona. Il tuo professore si sbaglia su questo punto. L'unico modo che potrebbe accadere è se StringBuffer chiama String.intern(), che non è, o almeno non è specificato per fare ..

2

Quello che ti manca è il concetto di string literal.

La stringa in aggiunta alla piscina quando:

  • Essa è definita come letterale.
  • Si invoca il metodo intern su di esso.

e non è già in piscina.

Nell'esempio si inseriscono stringhe letterali nell'oggetto di tipo StringBuffer. Per recuperare la stringa da quell'oggetto è necessario chiamare toString(). Per aggiungere il risultato al pool di stringhe, è necessario chiamare anche intern() su quella stringa.

Per dimostrare che possiamo eseguire un semplice test.

String s1 = "This is a simple test"; 
String s2 = "This is a simple test"; 

System.out.println(s1 == s2); 

StringBuffer sb1 = new StringBuffer(s1); 
StringBuffer sb2 = new StringBuffer(s2); 

String result1 = sb1.toString(); 
String result2 = sb2.toString(); 

System.out.println(result1 == result2); 

String internedResult1 = result1.intern(); 
String internedResult2 = result2.intern(); 

System.out.println(internedResult1 == internedResult2); 

L'uscita codice sarà:

vero
falso
veri

+0

Bel esempio! Penso che sia più facile da vedere qui –

Problemi correlati