简短的回答
行:
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,转换方法真正返回一个新 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;的原因是因为它促进了method chaining,允许您编写如下内容:
sb.append(thisThing).append(thatThing).append(oneMoreForGoodMeasure);
相关问题
附录:StringBuffer vs StringBuilder
您通常应该更喜欢StringBuilder,而不是StringBuffer,因为它不是synchronized,所以它更快。上面的大部分讨论也适用于StringBuilder。
来自文档:
StringBuffer:一个线程安全,可变的字符序列。 [...] 从 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"