根本原因是传入的索引超出 StringBuilder 当前长度范围,即不满足 0 ≤ start ≤ end ≤ length();需动态校验 start 和 end 是否合法,尤其注意 end 为不包含右边界且 length() 是实时值。

调用 StringBuilder.delete(int start, int end) 报 StringIndexOutOfBoundsException,根本原因是传入的索引超出了当前字符串的有效范围(即 0 ≤ start ≤ end ≤ length() 不成立)。排查关键在于验证两个索引是否合法,尤其注意 end 是“不包含”的右边界,且 StringBuilder 长度会随操作动态变化。
检查 start 和 end 是否在合法范围内
错误常发生在硬编码索引、计算偏移量出错,或未考虑字符串实时长度。必须确保:
-
start ≥ 0且start ≤ length() -
end ≥ start且end ≤ length() -
length()是调用时的**当前长度**,不是初始长度
例如:sb = new StringBuilder("abc"); sb.delete(2, 5); 中 length() 是 3,但 end=5 > 3,直接抛异常。
警惕 delete 后 length 变化影响后续操作
多次连续 delete 或与其他修改操作(如 append、replace)混用时,容易误用旧长度做索引计算。比如:
立即学习“Java免费学习笔记(深入)”;
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 先
sb.delete(0, 2)缩短了字符串,后续再用原长度算end就会越界 - 在循环中删除匹配内容时,没同步更新索引或没处理删除后位置偏移
建议每次 delete 前打印 sb.length() 和待删区间,或用 Math.min(end, sb.length()) 做防御性截断(需确认业务是否允许截断)。
用 substring 或 regionMatches 辅助定位问题位置
如果不确定越界发生在哪一步,可在 delete 前加校验逻辑:
if (start < 0 || start > sb.length() || end < start || end > sb.length()) {
throw new IllegalArgumentException("Invalid delete range: [" + start + ", " + end + "), length=" + sb.length());
}
或者用 sb.substring(start, Math.min(end, sb.length())) 预览将删内容,既避免异常又能调试实际删的是什么。
替代方案:用 deleteCharAt 或 replace 更安全
若只需删单个字符,优先用 deleteCharAt(int index)(只校验单个索引);若要替换一段内容,replace(int start, int end, String str) 的异常提示更明确,且语义更清晰。对复杂文本处理,也可先用 indexOf/lastIndexOf 获取位置,再判断是否存在再删,避免盲目传参。

















