应优先用 substring + indexOf 组合处理格式可控的字符串,因其零正则开销、错误易定位;外部不规则数据选 split 配预编译 Pattern;复杂语义提取务必用 Pattern + Matcher 捕获组。

substring 怎么用才不会越界
substring 是最轻量的截取方式,但它不校验分隔逻辑,只认索引。常见错误是传入负数或超出字符串长度的索引,直接抛 StringIndexOutOfBoundsException。
使用时必须先确认边界:
- 检查
beginIndex≥ 0 且 ≤endIndex - 检查
endIndex≤ 字符串长度(str.length()),注意它不包含结尾字符 - 若要从某字符首次出现后截取,得先调用
indexOf获取位置,再传给substring
例如想截取 "user:admin" 冒号后的部分:int pos = str.indexOf(':'); if (pos != -1) { String role = str.substring(pos + 1); }
split 为什么有时返回空数组或长度不对
split 表面简单,实则受正则和限制参数双重影响。默认按正则匹配切分,而点号 .、星号 *、括号等都是元字符,不转义就会误匹配。
典型陷阱:
立即学习“Java免费学习笔记(深入)”;
- 用
str.split(".")切分 IP 地址,结果得到空数组——因为.匹配任意字符,整串被全切没了 - 未传
limit参数时,末尾连续分隔符会被丢弃("a,b,,c,".split(",")返回长度为 4 的数组,最后的空串没了) - 想保留末尾空串,得显式传
-1:str.split(",", -1)
安全写法:切分固定符号优先用 Pattern.quote() 转义,比如 str.split(Pattern.quote("."))。
正则表达式 replaceAll/replaceAll 替代截取是否更灵活
严格来说正则不是“截取”方法,但常被用来提取子串,比如用 replaceAll 去掉不需要的部分,或用 Pattern + Matcher 捕获组精准提取。
适用场景明确:
- 需要按复杂模式识别边界(如“数字+下划线+字母”组合后的内容)
- 原始字符串结构不规整,无法靠固定分隔符定位
- 要同时校验格式并提取(如邮箱中取用户名部分)
但代价明显:性能比 substring 低一个数量级;写错正则容易匹配失败或回溯爆炸;replaceAll 中的反斜杠需双写("\\\\d+" 才表示一个或多个数字)。
该选哪个?看输入稳定性和性能要求
如果源字符串格式高度可控(如 API 返回的固定结构 JSON 片段、日志行),优先用 substring + indexOf 组合,零正则开销,出错也容易定位。
如果是用户输入或外部数据,含多种可能分隔方式(逗号/分号/空格),split 配合预编译的 Pattern 更稳妥。
真正复杂的语义提取(比如从一段话里抽“第X次失败,错误码YYY”中的数字和码),别硬套 substring 或 split,老实用 Pattern.compile(...).matcher(str).find() 加捕获组——多写几行代码,少 debug 两小时。











