可以,String.contentEquals()支持直接比较String与StringBuffer,仅逐字符比对内容,不创建新对象、不触发toString()、无同步开销,但需注意多线程下可能读到不一致状态。

String.contentEquals() 能否直接比较 String 和 StringBuffer
可以,String.contentEquals() 明确支持传入 StringBuffer(以及 StringBuilder、CharSequence 子类),它只比对字符序列内容,不关心可变性或线程安全性。
常见错误是误用 equals():比如 "abc".equals(new StringBuffer("abc")) 一定返回 false,因为 StringBuffer 没有重写 equals() 方法,会走 Object.equals() 做引用比较。
contentEquals() 的参数类型和实际行为
contentEquals() 接收一个 CharSequence 参数,StringBuffer 实现了该接口,所以能直接传入。方法内部逐字符对比,不创建新字符串,也不触发 toString() —— 这意味着没有额外对象分配,也没有同步开销(尽管 StringBuffer 本身是同步的,但 contentEquals() 只读取其内部 char[] 和 count 字段)。
- 传入
null会抛NullPointerException - 传入空
StringBuffer(如new StringBuffer())与空字符串""比较结果为true - 若
StringBuffer处于修改中(多线程场景下未加锁),contentEquals()仍可能读到不一致状态 —— 它不加锁,只是“快照式”读取当前count和底层数组
和 toString().equals() 对比:性能与安全边界
避免写成 str.equals(buf.toString()):这会强制触发 StringBuffer.toString(),后者新建一个 String 对象(即使内容相同),带来 GC 压力;而且在高并发下,toString() 内部会加锁,可能成为瓶颈。
立即学习“Java免费学习笔记(深入)”;
contentEquals() 绕过这些,更轻量。但要注意:它不处理编码或 Unicode 边界(比如代理对),和 equals() 行为一致,仅做 16-bit char 级别逐位比对。
示例:
String s = "hello";
StringBuffer buf = new StringBuffer("hello");
System.out.println(s.contentEquals(buf)); // true
buf.append(" world");
System.out.println(s.contentEquals(buf)); // false
容易被忽略的细节:CharSequence 兼容性陷阱
contentEquals() 接口宽泛,但并非所有 CharSequence 实现都适合。例如自定义的 CharSequence 若在 charAt() 中抛异常、或 length() 返回异常值,会导致 contentEquals() 抛出运行时异常。
另外,StringBuffer 的 capacity() 不影响比较结果 —— 只看 length() 范围内的字符。如果有人手动调用 buf.setLength(0) 清空但未清掉底层数组残留内容,contentEquals() 仍只读前 0 个字符,不会越界。
真正要小心的是:把 StringBuffer 当作“临时容器”反复复用时,没重置就直接比较,容易漏掉逻辑错误 —— 这不是方法的问题,而是使用模式问题。


















