StringBuilder vs StringBuffer: 10 principais diferenças em Java

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

StringBuilder vs StringBuffer: o que escolher e por que isso é importante?

\n\n

Se você já escreveu código Java que trabalha intensamente com strings (por exemplo, montando uma consulta SQL, gerando JSON ou simplesmente concatenando dezenas de fragmentos de texto), certamente já enfrentou o dilema: StringBuilder ou StringBuffer? No Stack Overflow, essa pergunta acumulou centenas de milhares de visualizações, e não é à toa. À primeira vista, as classes são como gêmeas — ambas estendem AbstractStringBuilder, ambas usam um array de caracteres mutável, ambas possuem append(), insert(), delete(). Mas o diabo, como sempre, está nos detalhes.

\n\n

Neste artigo, não vamos apenas listar as diferenças. Vamos analisá-las com exemplos reais, explorar os bastidores da JVM e responder às perguntas que certamente serão feitas em uma entrevista. Vamos lá!

\n\n

1. A principal diferença: sincronização

\n\n

Este é o ponto mais importante, a razão de toda a discussão. StringBuffer é thread-safe. Quase todos os seus métodos públicos são sincronizados com a palavra-chave synchronized. StringBuilder não é sincronizado. Ponto final.

\n\n

Vamos dar uma olhada no código (versão simplificada do JDK real):

\n\n
// StringBuffer (Java 17)\npublic synchronized StringBuffer append(String str) {\n    toStringCache = null;\n    super.append(str);\n    return this;\n}\n\n// StringBuilder\npublic StringBuilder append(String str) {\n    super.append(str);\n    return this;\n}\n
\n\n

Uma única linha synchronized — e toda a diferença. Mas essa linha muda tudo: desempenho, escopo de aplicação, até mesmo a arquitetura da aplicação.

\n\n

Quando usar StringBuffer?

\n
    \n
  • Você está escrevendo uma aplicação multithread.
  • \n
  • A mesma instância de StringBuffer é usada por várias threads sem sincronização externa.
  • \n
  • Exemplo: um logger que coleta mensagens de diferentes threads em um único buffer.
  • \n
\n\n

Quando usar StringBuilder?

\n
    \n
  • Código single-thread (90% dos casos).
  • \n
  • Variáveis locais dentro de um método.
  • \n
  • Loops com concatenação de strings (o compilador sugere StringBuilder automaticamente).
  • \n
\n\n

2. Desempenho: quem é mais rápido?

\n\n

Aqui tudo é previsível: StringBuilder é mais rápido que StringBuffer. Quanto? Depende da carga, mas em média de 2 a 5 vezes. Vamos verificar com um benchmark simples.

\n\n
public class PerformanceTest {\n    private static final int ITERATIONS = 10_000_000;\n\n    public static void main(String[] args) {\n        // StringBuilder\n        long start = System.nanoTime();\n        StringBuilder sb = new StringBuilder();\n        for (int i = 0; i < ITERATIONS; i++) {\n            sb.append("a");\n        }\n        long sbTime = System.nanoTime() - start;\n\n        // StringBuffer\n        start = System.nanoTime();\n        StringBuffer sbf = new StringBuffer();\n        for (int i = 0; i < ITERATIONS; i++) {\n            sbf.append("a");\n        }\n        long sbfTime = System.nanoTime() - start;\n\n        System.out.println("StringBuilder: " + sbTime / 1_000_000 + " ms");\n        System.out.println("StringBuffer:  " + sbfTime / 1_000_000 + " ms");\n        System.out.println("Buffer é " + (sbfTime / (double) sbTime) + " vezes mais lento");\n    }\n}\n
\n\n

No meu notebook (Intel i7, 16GB RAM, Java 17), o resultado é consistente: StringBuilder ~180 ms, StringBuffer ~620 ms. A diferença é de quase 3,5 vezes. E se adicionarmos trabalho real (parsing, formatação), a diferença pode aumentar. Por quê? Porque cada chamada synchronized envolve verificação do monitor, aquisição e liberação do bloqueio. Em código single-thread, isso é pura perda de tempo.

\n\n
\n Importante: Se o seu método garante

Blogs

Book Recommendations