最高频错误是调用s.substring(s.length()-n)未检查长度,导致stringindexoutofboundsexception;正确做法是先判断长度,按需使用math.max(0, s.length()-n)或提前校验。

用 substring 取末尾字符时,下标算错是最高频错误
Java 里没有类似 Python 的 s[-3:] 这种语法,必须手动算起始位置。常见错误是写成 s.substring(s.length() - n) 却没检查长度是否够——一旦 n > s.length(),直接抛 StringIndexOutOfBoundsException。
正确做法永远先做长度判断:
- 如果只要最后
n个字符,且允许返回少于n个(比如字符串本身更短),用Math.max(0, s.length() - n)作起始索引 - 如果要求“必须取满
n个”,就得提前if (s.length() - 注意
substring(beginIndex)是从beginIndex到末尾,不是取n个;要精确截取得用substring(beginIndex, endIndex)
示例:安全取最后 3 个字符
String s = "abc"; int n = 3; String last = s.substring(Math.max(0, s.length() - n)); // 结果 "abc"
substring 在 Java 9+ 的性能变化影响不大,但要注意内存
Java 7u6 之后 substring 已不再共享底层 char[],所以不用再担心“小字符串持大数组”问题。Java 9 引入紧凑字符串(byte[] + coder),substring 返回的新字符串会按需复制字节,内存开销可控。
不过仍要注意:频繁对超长字符串调用 substring 取末尾,不如先反转再取前缀——但除非真在 hot path 上,否则别过早优化。
- 纯 ASCII 字符串下,Java 9+ 的
substring比旧版略快一点,差异可忽略 - 如果原字符串是通过
StringBuilder.toString()得到的,且后续不再修改 builder,那它的toString()返回的是不可变副本,substring安全
替代方案:用 CharSequence 接口方法更灵活
如果你的代码需要兼容 String、StringBuilder 或其他实现,别硬写 String 方法。JDK 15+ 的 CharSequence 加了 subSequence,语义和 substring 一致,且不强制要求具体类型。
-
subSequence(begin, end)返回CharSequence,不是String,需要时再调.toString() - 对
String来说,subSequence就是substring的包装,无额外开销 - 某些自定义
CharSequence实现可能懒加载或流式处理,subSequence可能比先转String再substring更省内存
示例(JDK 15+):
CharSequence cs = "hello world"; CharSequence last3 = cs.subSequence(Math.max(0, cs.length() - 3), cs.length()); // "rld"
容易被忽略的边界:空字符串、null、代理对(surrogate pairs)
中文、emoji 等 Unicode 字符可能占两个 char(即一个代理对),这时 length() 返回的是 char 数,不是真正“字符数”。用 substring 截取末尾可能切在代理对中间,导致乱码。
- 如果业务关心“用户感知的字符数”,得用
codePointCount和offsetByCodePoints计算真实位置 - 空字符串
""调用substring(s.length() - n)一定出错,必须单独判断 -
null输入不被substring处理,得在外层判空,建议用Objects.requireNonNull(s)或 Apache Commons 的StringUtils.right(s, n)
emoji 场景示例(取最后 1 个“字符”,而非 1 个 char):
String s = "Hello ??"; // length() == 10,但用户觉得是 7 个字符 int cpLen = s.codePointCount(0, s.length()); int start = s.offsetByCodePoints(0, Math.max(0, cpLen - 1)); String lastChar = s.substring(start); // 正确得到 "??"
事情说清了就结束。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











