StringBuffer contro String

Java fornisce le StringBuffere Stringclassi, e la Stringclasse viene utilizzata per manipolare le stringhe di caratteri che non possono essere modificati. In parole semplici, gli oggetti di tipo Stringsono di sola lettura e immutabili. La StringBufferclasse viene utilizzata per rappresentare i caratteri che possono essere modificati.

La differenza di prestazioni significativa tra queste due classi è che StringBufferè più veloce rispetto Stringall'esecuzione di concatenazioni semplici. Nel Stringcodice di manipolazione, le stringhe di caratteri vengono regolarmente concatenate. Utilizzando la Stringclasse, le concatenazioni vengono in genere eseguite come segue:

String str = new String ("Stanford"); str + = "Lost !!";

Se dovessi usare StringBufferper 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 appendmetodo per la concatenazione, sia più costoso del primo esempio, che utilizza l' +operatore per concatenare due Stringoggetti.

L' +operatore sembra innocente, ma il codice generato produce alcune sorprese. L'utilizzo di un StringBufferper 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 StringBufferoggetto, quindi invoca il suo appendmetodo: l' StringBufferoggetto temporaneo viene creato nella posizione 10 e il suo appendmetodo viene chiamato nella posizione 23. Poiché la Stringclasse è immutabile, StringBufferper la concatenazione deve essere utilizzato a.

Dopo aver eseguito la concatenazione StringBuffersull'oggetto, è necessario riconvertirlo in un file String. Questo viene fatto con la chiamata al toStringmetodo nella posizione 26. Questo metodo crea un nuovo Stringoggetto dall'oggetto temporaneo StringBuffer. La creazione di questo StringBufferoggetto temporaneo e la sua successiva riconversione in un Stringoggetto sono molto costose.

In sintesi, le due righe di codice sopra portano alla creazione di tre oggetti:

  1. Un Stringoggetto nella posizione 0
  2. Un StringBufferoggetto nella posizione 10
  3. Un Stringoggetto 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 appendmetodo di un StringBufferoggetto. A differenza del primo esempio, tuttavia, non è necessario creare un temporaneo StringBuffere poi convertirlo in un Stringoggetto. Questo codice crea un solo oggetto, il StringBuffer, nella posizione 0.

In conclusione, la StringBufferconcatenazione è significativamente più veloce della Stringconcatenazione. Ovviamente StringBuffers dovrebbe essere usato in questo tipo di operazione quando possibile. Se Stringsi desidera la funzionalità della classe, considerare l'utilizzo di un StringBufferper la concatenazione e quindi eseguire una conversione in String.

Reggie Hutcherson è un evangelista della tecnologia Sun. Evangelizza le tecnologie della piattaforma Java 2 di Sun in tutto il mondo concentrandosi su J2SE e sul motore di prestazioni HotSpot.

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.