Java中substring()越界直接抛StringIndexOutOfBoundsException,需用Math.min()校验边界;replace()为字面替换,replaceAll()支持正则需转义;trim()仅处理ASCII空白。

substring() 裁剪字符串时索引越界会直接抛异常
Java 中 substring() 不像 Python 的切片那样容忍越界,beginIndex 小于 0 或大于 String.length(),或 endIndex 小于 beginIndex,都会触发 StringIndexOutOfBoundsException。
实操建议:
- 裁剪前先用
str.length()校验边界,尤其处理用户输入或 JSON 字段时 - 想“安全截取前 N 位”,别硬写
str.substring(0, N),改用str.substring(0, Math.min(N, str.length())) substring(begin, end)的end是**不包含**的,比如"abc".substring(1,2)得到的是"b",不是"bc"
replace() 和 replaceAll() 的行为差异远不止正则支持
replace() 只做字面量替换,参数是 char 或 CharSequence;replaceAll() 底层调用 Pattern.compile().matcher().replaceAll(),第一个参数是正则表达式。
常见错误现象:
- 想把字符串里的点号
"."全替换成下划线,写了str.replaceAll(".", "_")—— 结果整个字符串变成一串下划线,因为.在正则里匹配任意字符 - 用
replace()替换空格没问题,但想替换所有空白符(包括 \t、\n),必须用replaceAll("\\s", "_"),且注意双反斜杠要写对 replaceAll()性能明显低于replace(),高频调用场景(如日志清洗)优先选replace()
trim() 只去首尾 ASCII 空白,中文空格和全角空格完全无效
trim() 的判定逻辑是 c <= ' '(即 Unicode 值 ≤ 32),所以它对中文空格(U+3000)、全角空格(U+FFEF)、甚至 (U+00A0)都无感。
使用场景与替代方案:
- 处理网页表单提交的文本时,用户可能粘贴带中文空格的内容,
trim()后仍残留空白 —— 改用str.replaceAll("^\\s+|\\s+$", "")(注意这里 \s 覆盖 Unicode 空白) - 若需兼容旧版 JDK(如 JDK 7),
\s不支持 Unicode 空白,得显式写"^[\\u0000-\\u0020\\u3000\\uFEFF]+|[\\u0000-\\u0020\\u3000\\uFEFF]+$" strip()(JDK 11+)才是现代替代:它基于Character.isWhitespace(),能正确识别中文空格和各种 Unicode 分隔符
concat() 和 + 拼接在循环里性能差别极大
单独一次拼接,str.concat("suffix") 和 str + "suffix" 编译后几乎一样;但在循环中反复拼接,问题就来了。
关键影响:
str += "x"在每次迭代都新建StringBuilder→toString(),时间复杂度 O(n²)concat()每次都生成新字符串,同样不可控增长- 真正该用的是
StringBuilder:初始化时预估容量(如new StringBuilder(str.length() + 100)),避免内部数组多次扩容
容易被忽略的一点:字符串裁剪和替换操作本身不修改原字符串,但频繁创建中间字符串对象,GC 压力比想象中大,尤其在内存受限环境(如 Android 后台服务)。