Короткий ответ Все три класса работают со строками, но различаются неизменяемостью и потокобезопасностью. String неизменяем: любой «изменяющий» метод создаёт новую строку. StringBuilder и StringBuffer изменяемы: они модифицируют внутренний буфер через append, insert, replace, не создавая новые объекты. Методы StringBuffer объявлены synchronized, поэтому он потокобезопасен, но медленнее StringBuilder. Как это работает подробнее StringBuffer существует с Java 1.0, его методы синхронизированы; StringBuilder появился в Java 5 как несинхронизированный аналог. Вне циклов компилятор сам превращает конкатенацию через + в вызовы StringBuilder, но внутри цикла это не спасает от множества промежуточных объектов. String — неизменяемый, подходит для строк, которые не меняются; переиспользуется в пуле. StringBuilder — изменяемый, без синхронизации, самый быстрый в однопоточном коде; появился в Java 5. StringBuffer — изменяемый, методы synchronized, потокобезопасный, но медленнее; существует с Java 1.0. Компилятор — простая