String中的substring()方法详解

说明:本文基于JDK8进行讨论

substring()方法

substring()方法是 Java 中 String 类的一个常用方法,用于从一个字符串中提取其中的子串。
开发中比如我们需要提取一些指定位置的字符串,比如身份证号码的出生年月日等等。
方法主要有下面两个重载方法

String substring(int beginIndex)
String substring(int beginIndex, int endIndex)

从源码看,第一个方法就是把字符数组的length替换成第二个方法的endIndex参数而已
image.png
这里尤其需要注意第二个方法的参数beginIndex,endIndex

  • beginIndex:起始索引,包括起始索引。
  • endIndex:结束索引,不包含。(很重要,经常忽略造成越界异常)

下面我们举个例子对这两个方法进行说明

String str1 = "hello Java";
String sub1 = str1.substring(2); // 提取从索引6开始到末尾的子串    "llo Java"
String sub2 = str1.substring(2, 7); // 提取从索引2到5的子串  "llo J"
String sub3 = str1.substring(0); // 提取整个字符串  "hello Java"
String sub4 = str1.substring(0, str1.length()); // 提取整个字符串   "hello Java"
String sub5 = str1.substring(4, 4); // 空字符串   ""

再分析下:

public String substring(int beginIndex, int endIndex) {
    // 检查起始索引是否小于0
    if (beginIndex < 0) {
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    // 检查结束索引是否大于原始字符串长度
    if (endIndex > value.length) {
        throw new StringIndexOutOfBoundsException(endIndex);
    }
    // 计算子串的长度
    int subLen = endIndex - beginIndex;
    // 检查子串长度是否小于0
    if (subLen < 0) {
        throw new StringIndexOutOfBoundsException(subLen);
    }
    // 如果子串的起始索引为0,且结束索引为原始字符串长度,则返回原始字符串对象
    // 否则,通过提取原始字符数组的一部分创建一个新的字符串对象并返回
    return ((beginIndex == 0) && (endIndex == value.length)) ? 
            this : new String(value, beginIndex, subLen);
}

继续看new String(value, beginIndex, subLen)方法

public String(char value[], int offset, int count) {
    // 各种检查
    ...
    ...
    // 使用Arrays.copyOfRange方法从原始数组中复制一定范围的字符到新数组作为value
    this.value = Arrays.copyOfRange(value, offset, offset+count);
}


public static char[] copyOfRange(char[] original, int from, int to) {
    // 计算新数组的长度
    int newLength = to - from;
    // 如果新数组长度小于0,抛出异常
    if (newLength < 0)
        throw new IllegalArgumentException(from + " > " + to);
    // 创建新的字符数组
    char[] copy = new char[newLength];
    // 使用 System.arraycopy 方法将原始数组中指定范围的元素复制到新数组中
    System.arraycopy(original, from, copy, 0,
                     Math.min(original.length - from, newLength));
    return copy;
}

从上面的源码可以看出,在这个方法中,底层实际上重新new了一个String,使用 Arrays.copyOfRange() 关于Arrays.copyOfRange()方法的使用,从原始字符数组中复制所需的字符到新的字符数组中,然后用这个新的字符数组创建一个新的字符串对象。

这样做是确保了新的字符串对象拥有自己的字符数组,不再与原始字符串共享。这样做是为了避免潜在的内存泄漏问题,同时也确保了原始字符串如果不再被引用时可以被垃圾回收,因为它的字符数组不再被新的子字符串引用。

所以在JDK 8中,String.substring() 方法通过创建新的 String 对象以及新的字符数组来实现的,可以避免潜在的内存泄漏问题。

注意:

  • substring() 方法获取的是字符串的一个子串,但原始字符串本身不会被修改。
  • 参数索引必须大于等于0且小于字符串的长度(0 <= index < length())。
  • substring() 方法提取的子串包括 beginIndex 索引处的字符,但不包括 endIndex 索引处的字符。
  • 若 beginIndex == endIndex,则返回的子串为空字符串。
  • 11
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值