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. 使用技巧

  1. 快速获取后缀/前缀
    // 获取后5字符
    String suffix = sb.substring(sb.length() - 5);
    
    // 获取前3字符
    String prefix = sb.substring(0, 3);
    
  2. 结合索引方法动态截取
    // 截取第一个空格后的内容
    int firstSpace = sb.indexOf(" ");
    if(firstSpace != -1) {
        String afterSpace = sb.substring(firstSpace + 1);
    }
    
  3. 提取特定标记内容
    // 提取 <tag> 内的内容
    int start = sb.indexOf("<tag>") + 5;
    int end = sb.indexOf("</tag>");
    String content = sb.substring(start, end);
    

5. 常见错误

  1. 索引越界
    // 错误:end > length()
    String s = sb.substring(2, 20); // StringIndexOutOfBoundsException
    
    // 错误:start < 0
    String s = sb.substring(-1); // StringIndexOutOfBoundsException
    
  2. 忽略左闭右开规则
    // 实际截取索引 [2,5) → 位置2,3,4
    String s = sb.substring(2, 5); // 长度=3,不是4
    
  3. 误用返回值修改原对象
    // 错误:substring()返回String,不影响原缓冲区
    sb.substring(0, 4).toUpperCase(); // 原sb不变!
    

6. 注意事项

  1. 性能影响
    大字符串频繁截取会生成大量临时String对象,内存敏感场景需谨慎:
    // 低效:每次substring()创建新String
    for (int i = 0; i < 10000; i++) {
        String temp = largeSb.substring(i, i+10);
    }
    
  2. 空字符串处理
    // start = end 时返回空字符串(非null)
    String empty = sb.substring(3, 3); // ""
    
  3. Unicode字符安全
    支持多字节字符(如中文),按字符位置截取:
    StringBuffer sb = new StringBuffer("你好Java");
    String s = sb.substring(2, 6); // "Java"(一个中文占2个char位置)
    

7. 最佳实践与性能优化

  1. 避免多层嵌套截取
    // ❌ 低效:生成中间String对象
    String result = sb.substring(5).substring(0, 3);
    
    // ✅ 高效:一次性计算区间
    String result = sb.substring(5, 8);
    
  2. 复用StringBuilder/Buffer
    // 需要修改子串时,用新缓冲区操作
    String sub = sb.substring(2, 5);
    StringBuilder subBuilder = new StringBuilder(sub);
    subBuilder.append("!");
    
  3. 直接操作原缓冲区
    若需保留缓冲区特性,优先使用 delete()/setLength()
    // 等效于 sb.substring(0, 5) 但保留缓冲区
    sb.setLength(5);  // 直接修改原对象(慎用!会丢失后续内容)
    
  4. 内存敏感场景用字符数组
    // 超大字符串截取优化
    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[] 减少中间对象