Краткий ответ
Линия:
buf.append(buf.reverse());
по существу делает следующее:
buf.reverse(); // buf is now "redrum"
buf.append(buf);
Вот почему вы получаете "redrumredrum"
.
То есть buf.reverse()
не возвращает новый StringBuffer
, который противоположен buf
. Он возвращает buf
, после того как он перевернулся!
Есть много способов «исправить» это, но проще всего было бы явно создать новый StringBuffer
для обращения, так что-то вроде этого:
buf.append(new StringBuffer(str).reverse());
Более глубокое понимание: сравнение String
и StringBuffer
String
в Java неизменный . С другой стороны, StringBuffer
является изменяемым (именно поэтому, помимо прочего, вы можете append
вещи к нему).
Вот почему с String
метод преобразования действительно возвращает new String
. Вот почему что-то подобное "неправильно"
String str = "murder";
str.toUpperCase(); // this is "wrong"!!!
System.out.println(str); // still "murder"
Вместо этого вы хотите сделать:
String str = "murder";
str = str.toUpperCase(); // YES!!!
System.out.println(str); // now "MURDER"!!!
Однако ситуация далека от аналогии с StringBuffer
. Большинство StringBuffer
методов возвращают StringBuffer
, но они возвращают того же экземпляра, который был вызван ! Они НЕ возвращают новый StringBuffer
экземпляр. Фактически, вы можете отказаться от «результата», потому что эти методы уже выполнили то, что они делают, посредством различных мутаций (то есть побочных эффектов) в экземпляре, к которому он был применен.
Эти методы могли бы быть объявлены как void
, но причина, по которой они по существу return this;
вместо этого, заключается в том, что это облегчает сцепление методов , позволяя вам написать что-то вроде :
sb.append(thisThing).append(thatThing).append(oneMoreForGoodMeasure);
Похожие вопросы
Приложение: StringBuffer
против StringBuilder
Вместо StringBuffer
, вы обычно предпочитаете StringBuilder
, что быстрее, потому что это не synchronized
. Большая часть обсуждений выше также относится к StringBuilder
.
Из документации:
StringBuffer
: A поточно-ориентированный , изменяемая последовательность символов. [...] Начиная с JDK 5, этот класс был дополнен эквивалентным классом, предназначенным для использования одним потоком, StringBuilder
, который обычно должен быть предпочтительным, поскольку он поддерживает все те же операции, но быстрее, так как он выполняет нет синхронизации.
StringBuilder
: изменяемая последовательность символов. [...] Экземпляры StringBuilder
не безопасны для использования несколькими потоками. Если такая синхронизация требуется, то рекомендуется использовать StringBuffer
.
Похожие вопросы
Бонусный материал! Альтернативное решение!
Вот альтернативное «исправление» проблемы, которое возможно более читабельно:
StringBuilder word = new StringBuilder("murder");
StringBuilder worddrow = new StringBuilder(); // starts empty
worddrow.append(word).append(word.reverse());
System.out.println(worddrow); // "murderredrum"
Обратите внимание, что, хотя это хорошо для коротких строк, оно использует дополнительный буфер, что означает, что это не самый эффективный способ решения проблемы.
Смежные вопросы
Бонусный материал снова! Последний смех!
StringBuilder sb = new StringBuilder("ha");
sb.append(sb.append(sb));
System.out.println(sb); // "hahahaha"