Вопрос об обращении строки - PullRequest
3 голосов
/ 01 августа 2010

Я пытаюсь сделать простую манипуляцию строкой. ввод "убийство", я хочу получить "убийство".

я пробовал это

String str = "murder";
StringBuffer buf = new StringBuffer(str);
// buf is now "murder", so i append the reverse which is "redrum"
buf.append(buf.reverse());
System.out.println(buf);

но теперь я получаю "redrumredrum" вместо "murderredrum".

Может кто-нибудь объяснить, что не так с моей программой? спасибо.

Ответы [ 2 ]

13 голосов
/ 01 августа 2010

Краткий ответ

Линия:

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"
1 голос
/ 01 августа 2010
Сначала вызывается

buf.reverse (), который изменяет буфер строк для перерисовки.Теперь вы добавляете redrum к redrum

...