stringbuilder.replace() 直接修改原对象,参数为起始索引(含)、结束索引(不含)和替换字符串;索引越界抛异常,start不能大于end,null被转为"null",长度动态变化。

StringBuilder.replace() 的基本用法和参数含义
StringBuilder.replace() 是直接修改原对象的就地替换方法,不是返回新对象。它需要三个参数:start(起始索引,包含)、end(结束索引,不包含)和 str(用于替换的字符串)。注意:索引越界会抛出 StringIndexOutOfBoundsException,且 start 不能大于 end。
常见错误现象包括:把 end 当成“长度”传入、误以为索引从 1 开始、或在空 StringBuilder 上调用时未检查长度。
-
start和end都是基于当前内容长度的绝对位置,与后续追加无关 - 若
str为null,会被转为字符串"null",不是空字符串 - 替换后,
StringBuilder的长度会变化:新长度 = 原长度 − (end − start) + str.length()
替换时如何避免 StringIndexOutOfBoundsException
最常踩的坑是没校验索引范围。例如构建器当前长度为 5,却传入 replace(3, 10, "x"),就会崩溃。Java 不会自动截断 end。
安全做法是显式约束 end:用 Math.min(end, sb.length());同时确保 start ≥ 0 且 ≤ sb.length()。如果逻辑上允许“超出末尾则只覆盖到末尾”,就得自己做这层判断。
- 不要依赖文档里“自动处理边界”的幻想——
StringBuilder没有这种宽容机制 - 调试时可先打印
sb.length()和你要操作的start/end值 - 若需频繁按子串定位再替换(如替换所有 "old" 为 "new"),不如先用
toString().indexOf()找位置,再调replace(),别硬套正则或循环索引
与 String.replace() 和 StringBuilder.setCharAt() 的关键区别
String.replace() 返回新字符串,不可变;StringBuilder.replace() 修改自身,适合链式调用;而 setCharAt() 只能换单个字符,不能伸缩长度。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
性能上,replace() 涉及数组复制(删除旧段 + 插入新段),比 setCharAt() 开销大,但比反复 delete() + insert() 更简洁安全。
- 想只改一个字符?用
setCharAt(i, 'x'),别用replace(i, i+1, "x") - 想全局替换子串?
String.replace(CharSequence, CharSequence)更直观,但会新建对象;若已在用StringBuilder累积内容,就别中途转toString() -
replace(0, sb.length(), "new")等价于sb.setLength(0); sb.append("new"),但前者更短,后者更明确意图
实际替换场景中的典型写法示例
比如构建 SQL 语句时动态填充 WHERE 条件,初始为 "SELECT * FROM users WHERE 1=1",之后要替换成真实条件:
StringBuilder sql = new StringBuilder("SELECT * FROM users WHERE 1=1");
int wherePos = sql.indexOf("WHERE ") + "WHERE ".length();
sql.replace(wherePos, sql.length(), "age > 18 AND status = 'active'");
这个例子中,wherePos 是计算出来的安全起点,sql.length() 作为 end 表示删到最后。如果后续还要追加 ORDER BY,就得记下替换后的长度,或重新找位置。
- 别写
sql.replace(sql.indexOf("1=1"), sql.length(), "...")—— 若 "1=1" 在别处也出现,indexOf()会错位 - 若替换内容含双引号或单引号,注意 Java 字符串字面量转义,不是
replace()本身的问题 - 多线程环境下不能共享同一
StringBuilder实例调用replace(),它不是线程安全的
替换操作看着简单,真正麻烦的是索引来源是否可靠、是否考虑了并发或空状态——这些地方一漏,运行时才报错,很难静态发现。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










