Strings são classes imutáveis. Nenhum método da classe String jamais modifica seu conteúdo. Apenas cópias da String original modificadas são retornadas.
O que significa que se vc fizer:
String nome = "Vinícius";
String sobrenome = " Godoy";
String nome += sobrenome;
Você terá gerado uma terceira String chamada “Vinícius Godoy” e só então terá atribuído ao nome (que ainda conterá “Vinícius”, até que a atribuição seja feita).
Isso tem um problema sério: se você precisar mudar muito uma String, você terá um impacto muito negativo na performance, pois ficará criando objetos a torto e a direita.
O StringBuilder resolve esse problema, pois ele é uma espécie de versão modificável da String. O método append faz uma concatenação de texto, com a diferença de que um novo string builder não é gerado. Quando vc termina de montar seu texto, basta chamar o método toString() do StringBuilder, para gerar a String final, imodificável.
O StringBuffer é idêntico ao StringBuilder, mas tem todos os métodos sincronizados. Por isso, na maior parte das vezes ele é mais ineficiente, e não deve ser utilizado.
O código que vc criou cria um StringBuffer vazio, concatena o texto “\n stop”) ao final dele e, implicitamente, chama o toString() (quando o println é feito, ele dá um toString() no objeto que vc passar por parâmetro).