StringBuilder vs concatenación en toString(): cómo funciona bajo el capó

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

StringBuilder vs concatenación en toString(): cómo funciona bajo el capó

\n\n

¿Alguna vez te has preguntado por qué en Stack Overflow todavía hay debates sobre cómo escribir correctamente toString() en Java? Algunos desarrolladores creen firmemente que StringBuilder es el único camino correcto. Otros usan tranquilamente la concatenación simple con el signo más y no se preocupan. ¿Quién tiene la razón?

\n\n

Echemos un vistazo bajo el capó del compilador de Java y del optimizador JIT (Just-In-Time). Descubrirá lo que realmente sucede cuando escribe str1 + str2 y por qué en 2024 la respuesta a esta pregunta podría sorprenderle.

\n\n

¿Por qué este tema es tan popular?

\n\n

La pregunta "StringBuilder vs String concatenation in toString()" ha acumulado miles de visitas en Stack Overflow por una razón. Cada desarrollador de Java ha escrito el método toString() al menos una vez. Y todos se han enfrentado a la elección: escribir de forma elegante con el signo más o "correctamente" con StringBuilder.

\n\n

El mito de que la concatenación de cadenas en Java siempre es lenta ha existido durante más de 20 años. Y era cierto... en la era de Java 1.4 y Java 5. Pero los compiladores no se quedan quietos.

\n\n

¿Qué dice la especificación de Java?

\n\n

Según la especificación del lenguaje Java (JLS §15.18.1), el operador + para cadenas es azúcar sintáctico. El compilador está obligado a transformar la concatenación de cadenas en código eficiente. Desde Java 5 (J2SE 5.0), el compilador javac reemplaza automáticamente la concatenación con el uso de StringBuilder.

\n\n

Verifiquemos esto en la práctica.

\n\n

Ejemplo de código: un toString() simple

\n\n

Tomemos un ejemplo clásico: el método toString() para la clase Person:

\n\n
public class Person {\n    private String name;\n    private int age;\n    private String email;\n\n    @Override\n    public String toString() {\n        return "Person{" +\n                "name='" + name + '\\'' +\n                ", age=" + age +\n                ", email='" + email + '\\'' +\n                '}';\n    }\n}\n
\n\n

Se ve limpio y legible. Pero, ¿cómo se ve en bytecode?

\n\n

Echando un vistazo al bytecode

\n\n

Compilemos esta clase y veamos el bytecode con javap -c Person.class:

\n\n
public java.lang.String toString();\n    Code:\n       0: new           #7    // class java/lang/StringBuilder\n       3: dup\n       4: invokespecial #8    // Method StringBuilder."<init>":()V\n       7: ldc           #9    // String "Person{name='"\n       9: invokevirtual #10   // StringBuilder.append(String)\n      12: aload_0\n      13: getfield      #3    // Field name:Ljava/lang/String;\n      16: invokevirtual #10   // StringBuilder.append(String)\n      19: ldc           #11   // String "', age="\n      21: invokevirtual #10   // StringBuilder.append(String)\n      24: aload_0\n      25: getfield      #4    // Field age:I\n      28: invokevirtual #12   // StringBuilder.append(int)\n      31: ldc           #13   // String ", email='"\n      33: invokevirtual #10   // StringBuilder.append(String)\n      36: aload_0\n      37: getfield      #5    // Field email:Ljava/lang/String;\n      40: invokevirtual #10   // StringBuilder.append(String)\n      43: ldc           #14   // String "'}"\n      45: invokevirtual #10   // StringBuilder.append(String)\n      48: invokevirtual #15   // StringBuilder.toString():String\n      51: areturn\n
\n\n

¿Lo ves? ¡El compilador creó su propio StringBuilder! Crea un nuevo objeto StringBuilder, llama a append() para cada parte de la cadena y luego a toString(). Es lo mismo que habrías escrito manualmente, pero con un código fuente más legible.

\n\n

¿Y qué pasa con un StringBuilder explícito?

\n\n

Ahora escribamos la versión con un StringBuilder explícito:

\n\n
@Override\npublic String toString() {\n    Strin                

Blogs

Book Recommendations