1. 方法定义
// 截取 [start, end) 区间的字符串(返回新String对象)
public String substring(int start)
public String substring(int start, int end)
2. 功能说明
方法 |
作用 |
substring(int start) |
截取从 start 到末尾的子字符串 |
substring(int start, int end) |
截取 [start, end) 区间的子字符串 |
关键特性:
- 不修改原缓冲区:返回独立的新String对象
- 左闭右开区间:包含
start
,不包含 end
- 索引校验:
start
必须合法,end
不可越界
3. 示例代码
StringBuffer sb = new StringBuffer("Programming");
// 截取 [4, end) → "mming"
String s1 = sb.substring(4);
// 截取 [3, 7) → "gram"
String s2 = sb.substring(3, 7);
// 链式操作(需注意返回值类型)
String result = new StringBuffer("Java")
.append("Script")
.substring(4); // "Script"
4. 使用技巧
- 快速获取后缀/前缀
// 获取后5字符
String suffix = sb.substring(sb.length() - 5);
// 获取前3字符
String prefix = sb.substring(0, 3);
- 结合索引方法动态截取
// 截取第一个空格后的内容
int firstSpace = sb.indexOf(" ");
if(firstSpace != -1) {
String afterSpace = sb.substring(firstSpace + 1);
}
- 提取特定标记内容
// 提取 <tag> 内的内容
int start = sb.indexOf("<tag>") + 5;
int end = sb.indexOf("</tag>");
String content = sb.substring(start, end);
5. 常见错误
- 索引越界
// 错误:end > length()
String s = sb.substring(2, 20); // StringIndexOutOfBoundsException
// 错误:start < 0
String s = sb.substring(-1); // StringIndexOutOfBoundsException
- 忽略左闭右开规则
// 实际截取索引 [2,5) → 位置2,3,4
String s = sb.substring(2, 5); // 长度=3,不是4
- 误用返回值修改原对象
// 错误:substring()返回String,不影响原缓冲区
sb.substring(0, 4).toUpperCase(); // 原sb不变!
6. 注意事项
- 性能影响
大字符串频繁截取会生成大量临时String对象,内存敏感场景需谨慎:
// 低效:每次substring()创建新String
for (int i = 0; i < 10000; i++) {
String temp = largeSb.substring(i, i+10);
}
- 空字符串处理
// start = end 时返回空字符串(非null)
String empty = sb.substring(3, 3); // ""
- Unicode字符安全
支持多字节字符(如中文),按字符位置截取:
StringBuffer sb = new StringBuffer("你好Java");
String s = sb.substring(2, 6); // "Java"(一个中文占2个char位置)
7. 最佳实践与性能优化
- 避免多层嵌套截取
// ❌ 低效:生成中间String对象
String result = sb.substring(5).substring(0, 3);
// ✅ 高效:一次性计算区间
String result = sb.substring(5, 8);
- 复用StringBuilder/Buffer
// 需要修改子串时,用新缓冲区操作
String sub = sb.substring(2, 5);
StringBuilder subBuilder = new StringBuilder(sub);
subBuilder.append("!");
- 直接操作原缓冲区
若需保留缓冲区特性,优先使用 delete()
/setLength()
:
// 等效于 sb.substring(0, 5) 但保留缓冲区
sb.setLength(5); // 直接修改原对象(慎用!会丢失后续内容)
- 内存敏感场景用字符数组
// 超大字符串截取优化
char[] buffer = new char[end - start];
sb.getChars(start, end, buffer, 0);
String result = new String(buffer);
总结
关键点 |
操作建议 |
方法选择 |
单边界截取 → substring(start) , 双边界截取 → substring(start, end) |
性能陷阱 |
避免循环内频繁截取大字符串,优先计算最终区间 |
索引规则 |
牢记 0 ≤ start ≤ end ≤ length() ,左闭右开 |
修改原对象 |
substring() 不修改缓冲区,需修改时用 delete() /setLength() |
内存优化 |
超大文本用 getChars() + char[] 减少中间对象 |