为何Java中使用字符串长度作为substring的起始索引不抛出越界异常?
为什么String.substring允许起始索引等于字符串长度
首先要区分两个很容易被混淆的概念:字符访问索引和字符串切割边界。
对于长度为n的字符串,每个实际存储的字符对应的可访问索引范围是0 ~ n-1,这个范围是严格不能越界的;但用于截取、切割的边界位置,合法范围是0 ~ n,一共n+1个可选择的位置,分别对应字符串最开头、每两个相邻字符的间隙、字符串最末尾的位置。
拿你举的"holy"(长度4)举例子,所有合法切割边界是:
- 边界0:h的前面,切这里开始就是整个字符串"holy"
- 边界1:h和o之间,切这里开始就是"oly"
- 边界2:o和l之间,切这里开始就是"ly"
- 边界3:l和y之间,切这里开始就是"y"
- 边界4:y的后面,也就是字符串最末尾,切这里开始就没有剩余字符,返回空串
这种设计从JDK1.0版本定下来开始,核心目的就是减少冗余的边界判断:
- 当你做遍历切割、生成全量字符串后缀、按规则截断字符串这类场景时,完全不需要为“索引刚好走到字符串末尾”的情况单独加兜底判断。比如你要遍历取出字符串的所有后缀,直接从i=0循环到i=字符串长度,调用
substring(i)就能拿到全部结果——其中i等于长度时返回的空字符串,本身就是字符串后缀集合的合法组成部分。 - 从底层逻辑看,substring截取的是
[beginIndex, endIndex)的左闭右开区间,当beginIndex等于字符串长度时,方法默认的endIndex(也就是字符串本身的长度)和beginIndex完全相等,整个截取区间的长度为0,根本不需要访问任何实际存储的字符,自然不存在越界风险。
只有当beginIndex为负数,或者数值严格大于字符串长度时,才会因为找不到对应的合法切割边界、甚至出现区间起点大于终点的非法情况,抛出IndexOutOfBoundsException。你之前查阅的Javadoc规则本身是准确的:触发异常的阈值是beginIndex大于字符串长度,而非大于等于字符串长度。
内容的提问来源于stack exchange,提问作者genghiskhang
相关产品推荐
相关产品推荐

