substring 方法用于从字符串中提取一个子字符串(即原字符串的一部分),Java 中主要有两种形式的 substring 方法,它们位于 String 类和 StringBuilder/StringBuffer 类中。

String 类中的 substring 方法
这是最常用的情况,用于从一个不可变的字符串 String 中创建一个新的子字符串。
substring(int beginIndex)
这个方法从指定的 beginIndex 索引处开始,截取到字符串的末尾。
语法:
public String substring(int beginIndex)
参数:

beginIndex:开始截取的索引(包含),索引从0开始。
返回值:
- 一个新的
String对象,包含从beginIndex到原字符串末尾的所有字符。
示例:
public class SubstringExample1 {
public static void main(String[] args) {
String str = "Hello, World!";
// 从索引 7 开始截取
String subStr = str.substring(7);
System.out.println("原始字符串: " + str); // 输出: Hello, World!
System.out.println("截取后的字符串: " + subStr); // 输出: World!
}
}
substring(int beginIndex, int endIndex)
这个方法从指定的 beginIndex 索引处开始,截取到 endIndex 索引处之前结束。注意:endIndex 索引处的字符不包含在结果中。
语法:

public String substring(int beginIndex, int endIndex)
参数:
beginIndex:开始截取的索引(包含)。endIndex:结束截取的索引(不包含)。
返回值:
- 一个新的
String对象,包含从beginIndex到endIndex-1的所有字符。
示例:
public class SubstringExample2 {
public static void main(String[] args) {
String str = "Hello, World!";
// 从索引 7 开始,截取到索引 12 之前
String subStr = str.substring(7, 12);
System.out.println("原始字符串: " + str); // 输出: Hello, World!
System.out.println("截取后的字符串: " + subStr); // 输出: World
}
}
StringBuilder 和 StringBuffer 中的 substring 方法
StringBuilder 和 StringBuffer 是可变的字符序列,它们也提供了 substring 方法,但行为略有不同。
方法:substring(int beginIndex) 和 substring(int beginIndex, int endIndex)
这两个方法的功能与 String 类中的同名方法类似,但返回值类型是 CharSequence,而不是 String。
语法:
public CharSequence substring(int beginIndex) public CharSequence substring(int beginIndex, int endIndex)
返回值:
- 一个
CharSequence对象,它代表了子字符串序列。
如何使用:
我们会将返回的 CharSequence 转换为 String 来使用。
示例:
public class StringBuilderSubstringExample {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Hello, Java!");
// 使用 substring 方法
CharSequence cs1 = sb.substring(7); // 返回 CharSequence
CharSequence cs2 = sb.substring(7, 11); // 返回 CharSequence
// 将 CharSequence 转换为 String
String subStr1 = cs1.toString();
String subStr2 = cs2.toString();
System.out.println("原始 StringBuilder: " + sb); // 输出: Hello, Java!
System.out.println("截取后的 CharSequence: " + cs1); // 输出: Java!
System.out.println("转换为 String 后: " + subStr1); // 输出: Java!
System.out.println("指定范围的截取: " + subStr2); // 输出: Java
}
}
重要注意事项
索引越界异常 (StringIndexOutOfBoundsException)
这是使用 substring 时最常见的错误,如果提供的索引值不合法,程序就会抛出 StringIndexOutOfBoundsException。
不合法的索引包括:
beginIndex或endIndex为负数。beginIndex大于字符串的长度 (str.length())。endIndex大于字符串的长度 (str.length())。beginIndex大于endIndex。
示例:
String str = "Hello"; // str.substring(-1); // 抛出异常 // str.substring(5); // 正常,结果是空字符串 "" // str.substring(6); // 抛出异常 // str.substring(1, 5); // 正常 // str.substring(1, 6); // 抛出异常 // str.substring(3, 2); // 抛出异常
beginIndex 和 endIndex 的范围
beginIndex的有效范围是[0, str.length()]。endIndex的有效范围是[0, str.length()]。beginIndex等于str.length(),结果将是一个空字符串 。beginIndex等于endIndex,结果也将是一个空字符串 。
字符串不可变性
String 对象是不可变的。substring 方法不会修改原始字符串,而是创建并返回一个新的 String 对象。
示例:
String original = "I am a String";
String modified = original.substring(5, 7);
System.out.println("原始字符串: " + original); // 输出: I am a String
System.out.println("新字符串: " + modified); // 输出: a
System.out.println("original 是否等于 modified? " + (original == modified)); // 输出: false
Java 8 新增:subSequence(int beginIndex, int endIndex)
Java 8 在 String 类中新增了 subSequence 方法,它的功能与 substring(int beginIndex, int endIndex) 完全相同,只是返回类型是 CharSequence。
public CharSequence subSequence(int beginIndex, int endIndex)
使用场景:
当你需要一个通用的字符序列接口 CharSequence 而不是具体的 String 类型时,可以使用这个方法,这通常用于更通用的 API 设计中。
示例:
String str = "Hello, World!"; CharSequence cs = str.subSequence(7, 12); System.out.println(cs.toString()); // 输出: World
总结与最佳实践
| 方法 | 所在类 | 功能 | 返回类型 | 示例 |
|---|---|---|---|---|
substring(int beginIndex) |
String |
从 beginIndex 截取到末尾 |
String |
str.substring(7) -> "World!" |
substring(int beginIndex, int endIndex) |
String |
从 beginIndex 截取到 endIndex 之前 |
String |
str.substring(7, 12) -> "World" |
substring(int beginIndex) |
StringBuilder |
从 beginIndex 截取到末尾 |
CharSequence |
sb.substring(7).toString() -> "Java!" |
substring(int beginIndex, int endIndex) |
StringBuilder |
从 beginIndex 截取到 endIndex 之前 |
CharSequence |
sb.substring(7, 11).toString() -> "Java" |
subSequence(int beginIndex, int endIndex) |
String |
从 beginIndex 截取到 endIndex 之前 |
CharSequence |
str.subSequence(7, 12).toString() -> "World" |
最佳实践:
- 对于
String对象,优先使用substring(int beginIndex, int endIndex),因为它可以精确控制截取的范围。 - 始终检查索引的有效性,或者使用
try-catch块来捕获StringIndexOutOfBoundsException,避免程序意外终止。 String是不可变的,substring操作会创建新对象,在需要频繁修改字符串内容的场景下,应考虑使用StringBuilder或StringBuffer。- 如果你的代码设计依赖于
CharSequence接口,StringBuilder.substring()或String.subSequence()会是更好的选择。
