StringBuffer contro String
Java fornisce le StringBuffer
e String
classi, e la String
classe viene utilizzata per manipolare le stringhe di caratteri che non possono essere modificati. In parole semplici, gli oggetti di tipo String
sono di sola lettura e immutabili. La StringBuffer
classe viene utilizzata per rappresentare i caratteri che possono essere modificati.
La differenza di prestazioni significativa tra queste due classi è che StringBuffer
è più veloce rispetto String
all'esecuzione di concatenazioni semplici. Nel String
codice di manipolazione, le stringhe di caratteri vengono regolarmente concatenate. Utilizzando la String
classe, le concatenazioni vengono in genere eseguite come segue:
String str = new String ("Stanford"); str + = "Lost !!";
Se dovessi usare StringBuffer
per eseguire la stessa concatenazione, avresti bisogno di codice simile a questo:
StringBuffer str = new StringBuffer ("Stanford"); str.append ("Lost !!");
Gli sviluppatori di solito presumono che il primo esempio sopra sia più efficiente perché pensano che il secondo esempio, che utilizza il append
metodo per la concatenazione, sia più costoso del primo esempio, che utilizza l' +
operatore per concatenare due String
oggetti.
L' +
operatore sembra innocente, ma il codice generato produce alcune sorprese. L'utilizzo di un StringBuffer
per la concatenazione può infatti produrre codice che è significativamente più veloce rispetto all'utilizzo di un file String
. Per scoprire perché questo è il caso, dobbiamo esaminare il bytecode generato dai nostri due esempi. Il bytecode per l'esempio che usa String
è simile a questo:
0 new # 7 3 dup 4 ldc # 2 6 invokespecial # 12 9 astore_1 10 new # 8 13 dup 14 aload_1 15 invokestatic # 23 18 invokespecial # 13 21 ldc # 1 23 invokevirtual # 15 26 invokevirtual # 22 29 astore_1
Il bytecode nelle posizioni da 0 a 9 viene eseguito per la prima riga di codice, ovvero:
String str = new String ("Stanford");
Quindi, il bytecode nella posizione da 10 a 29 viene eseguito per la concatenazione:
str + = "Lost !!";
Le cose si fanno interessanti qui. Il bytecode generato per la concatenazione crea un StringBuffer
oggetto, quindi invoca il suo append
metodo: l' StringBuffer
oggetto temporaneo viene creato nella posizione 10 e il suo append
metodo viene chiamato nella posizione 23. Poiché la String
classe è immutabile, StringBuffer
per la concatenazione deve essere utilizzato a.
Dopo aver eseguito la concatenazione StringBuffer
sull'oggetto, è necessario riconvertirlo in un file String
. Questo viene fatto con la chiamata al toString
metodo nella posizione 26. Questo metodo crea un nuovo String
oggetto dall'oggetto temporaneo StringBuffer
. La creazione di questo StringBuffer
oggetto temporaneo e la sua successiva riconversione in un String
oggetto sono molto costose.
In sintesi, le due righe di codice sopra portano alla creazione di tre oggetti:
- Un
String
oggetto nella posizione 0 - Un
StringBuffer
oggetto nella posizione 10 - Un
String
oggetto nella posizione 26
Ora, diamo un'occhiata al bytecode generato per l'esempio utilizzando StringBuffer
:
0 nuovo # 8 3 dup 4 ldc # 2 6 invokespecial # 13 9 astore_1 10 aload_1 11 ldc # 1 13 invokevirtual # 15 16 pop
Il bytecode nelle posizioni da 0 a 9 viene eseguito per la prima riga di codice:
StringBuffer str = new StringBuffer ("Stanford");
Il bytecode nella posizione da 10 a 16 viene quindi eseguito per la concatenazione:
str.append ("Lost !!");
Si noti che, come nel primo esempio, questo codice richiama il append
metodo di un StringBuffer
oggetto. A differenza del primo esempio, tuttavia, non è necessario creare un temporaneo StringBuffer
e poi convertirlo in un String
oggetto. Questo codice crea un solo oggetto, il StringBuffer
, nella posizione 0.
In conclusione, la StringBuffer
concatenazione è significativamente più veloce della String
concatenazione. Ovviamente StringBuffer
s dovrebbe essere usato in questo tipo di operazione quando possibile. Se String
si desidera la funzionalità della classe, considerare l'utilizzo di un StringBuffer
per la concatenazione e quindi eseguire una conversione in String
.
Ulteriori informazioni su questo argomento
- " JavaWorld fa il suo debutto nella nuova rubrica settimanale sulle prestazioni di Java", Reggie Hutcherson ( JavaWorld, marzo 2000)
//www.javaworld.com/jw-03-2000/jw-03-javaperf.html
- "The basics of Java performance", Reggie Hutcherson ( JavaWorld, marzo 2000)
//www.javaworld.com/jw-03-2000/jw-03-javaperf_2.html
- "Problema di prestazioni o problema di progettazione?" Reggie Hutcherson ( JavaWorld, marzo 2000)
//www.javaworld.com/jw-03-2000/jw-03-javaperf_3.html
- "Ottimizzazioni del compilatore", Reggie Hutcherson ( JavaWorld, marzo 2000)
//www.javaworld.com/jw-03-2000/jw-03-javaperf_4.html
Questa storia, "StringBuffer contro String" è stata originariamente pubblicata da JavaWorld.