Diferencias entre String, StringBuffer y StringBuilder, Java

Hoy vamos a entender las diferencias entre String, StringBuilder y StringBuffer. Como se darán cuenta existen pequeñas diferencias entre las clases antes mencionadas.

String

String es un objeto inmutable (una vez creado no se puede cambiar). El objeto creado como un String se almacena en la Constant String Pool.

Cada objeto inmutable en Java es seguro para su utilización en los hilos, que implica que el String es thread safe. Un String no puede ser utilizado por dos hilos simultáneamente.

Una vez asignado un valor a un String este no se puede modificar.

String demo = "Hola"; // El objeto anterior se almacena en la Constant String Pool y su valor no se puede modificar.

demo = "Adiós"; // El nuevo String "Adiós" se crea en la Constant String Pool y es referenciado por la variable demo

//El String "Hola" todavía existe en la Constant String Pool y su valor no se sobreescribe pero perdimos la referencia al String "hola"

StringBuffer

StringBuffer es mutable significa que podemos cambiar el valor del objeto. El objeto creado a través de StringBuffer se almacena en el Heap. StringBuffer tiene los mismos métodos que el StringBuilder, pero cada método en el StringBuffer es sincronizado, esto quiere decir que StringBuffer estara protegido al usarse en hilos , es thread safe.

Debido a esto no se permite que dos hilos puedan acceder simultáneamente a el mismo método. Cada método se puede acceder por un hilo a la vez.

Pero al estar protegido en los hilos tiene desventajas en el rendimiento del StringBuffer. Así StringBuilder es más rápido que el StringBuffer al llamar a los mismos métodos de cada clase.

En el StringBuffer el valor puede ser modificado, significa que se puede asignar un nuevo valor. Hoy en día es una de las preguntas de entrevista más común, las diferencias entre las clases anteriores.
StringBuffer se puede convertir a String mediante el uso del
método toString().

StringBuffer demo1 = new StringBuffer ("Hola");
// El objeto anterior se almacena en el Heap y su valor se puede modificar.
demo1 = new StringBuffer ("Adiós");
// La declaración anterior es correcta, ya que modifica el valor que se encuentra en el StringBuffer

StringBuilder

StringBuilder es igual que StringBuffer, se almacena el objeto en el Heap y también se puede modificar. La principal diferencia entre el StringBuffer y el StringBuilder es que StringBuilder no es seguro al utilizarse en hilos.
StringBuilder es rápido ya que no es seguro al utilizarse en los hilos, no es thread safe.

StringBuilder demo2 = new StringBuilder ("Hola");
// El objeto anterior también se almacena en el heap y su valor puede ser modificado
demo2 = new StringBuilder ("Adiós");
// La declaración anterior es correcta, ya que modifica el valor que se encuentra en el StringBuilder
  <td>
    Constant String Pool
  </td>

  <td>
    Heap
  </td>

  <td>
    Heap
  </td>

</tr>

<tr>
  <td>
    Modificable
  </td>

  <td>
    No(inmutable)
  </td>

  <td>
    Si(mutable)
  </td>

  <td>
    Si(mutable)
  </td>

</tr>

<tr>
  <td>
    Thread Safe(Seguro al utilizarse en hilos)
  </td>

  <td>
    Si
  </td>

  <td>
    Si
  </td>

  <td>
    No
  </td>
</tr>

<tr>
  <td>
    Rendimiento
  </td>

  <td>
    Rapido
  </td>

  <td>
    Muy lento
  </td>

  <td>
    Rapido
  </td>
</tr>
String StringBuffer StringBuilder
Área de almacenamiento

Por favor mencione en los comentarios si tiene dudas relacionadas con el articulo: diferencias entre el String, StringBuffer y StringBuilder.

Nota

Este articulo es una traducción de una publicación en ingles, pero en el no se explican algunos conceptos importantes para el entendimiento de por que se requieren estas tres clases para manejar cadenas de caracteres, trataremos de explicarlos.

¿ Qué es la Constant String Pool ?

Se trata de una zona de memoria donde se almacenan las referencias a los objetos String. De esta manera, cada vez que se crea un String, la máquina virtual de Java primero comprueba si la cadena se encuentra en el String Constant Pool, si la cadena ya existe devuelve la referencia a la cadena existente, y si la cadena no existe se crea un nuevo objeto String, cuya referencia es colocada en la String Constant Pool gracias a esto se evita tener en memoria muchos objetos de tipo String con el mismo contenido. Además, los objetos String apuntados en la String Constant Pool nunca son elegibles por el recolector de basura, ya que la referencia a estos objetos siempre esta en uso. debido a estas dos características se consiguió optimizar el rendimiento de las aplicaciones y el uso de memoria.

El siguiente es un código de prueba que utilice para ver cuales eran los tiempos de respuesta para cada clase al concatenar un numero determinado de palabras :

Estos fueron los resultados de 3 iteraciones del programa :

Uno

Tiempo del StringBuffer: 2909

Tiempo del StringBuilder: 1141

Dos

Tiempo del StringBuffer: 2810

Tiempo del StringBuilder: 1111

Tres

Tiempo del StringBuffer: 3755

Tiempo del StringBuilder: 1638

Como podemos observar en primera instancia faltan los resultados de los métodos testStringWithoutConcat y testStringWithConcat , esto paso por que los métodos tardaron demasiado en regresar el resultado y no me quedo otro remedio que obviarlo y apuntar que es una muy mala practica concatenar cadenas de texto utilizando el signo de +,su equivalente += o el método concat en la clase String, también resaltar que el StringBuilder resulto ser mucho mas eficiente que las otras dos clases, en definitiva esta prueba es solo para fines demostrativos ya que se deben utilizar cada cual dependiendo del contexto en el que nos encontremos, el código de esta prueba es posible encontrarlo aquí.

Fuentes