为什么不使用字符串的长度作为起始索引调用子字符串会引发 OutOfBoundsException?



在测试某些代码时,我注意到如果我使用的索引等于字符串的长度,那么子字符串方法不会抛出异常。例如:

String s = "holy";
System.out.println(s.substring(4));

输出将不返回任何内容,但不会引发异常。但如果我试着打电话:

String s = "holy";
System.out.println(s.substring(5));

它将抛出IndexOutOfBoundsException。我阅读了该方法的Javadoc,上面写着

如果beginIndex为负数或大于此String对象的长度。

有人知道为什么它允许起始索引等于字符串长度吗?

考虑substring:的其他调用

"holy".substring(n)

可以被可视化为复制CCD_ 2(包括(和字符串末尾(不包括(之间的字符范围。

例如:

"holy".substring(0)`
h o l y
O-------X    (O = start, X = end)
0 1 2 3 4

也就是说,开始位置刚好在角色之前,结束位置正好在角色之后。在这种情况下,得到的字符串长度是end - start,4。

"holy".substring(1)
h o l y
O-----X     // length = 4 - 1 = 3.
0 1 2 3 4

等等。然后:

"holy".substring(4)

可以可视化为

h o l y
O     // O and X are at the same position
X     // length = 4 - 4 = 0
0 1 2 3 4

O和X在同一位置也没关系:这只是意味着结果是一个零长度的字符串""

但是,将指数提高到5:

"holy".substring(5)
h o l y
X-O    // O is after X
// length = 4 - 5 = -1 (?!)
0 1 2 3 4 5

长度为-1的字符串没有意义,因此出现了异常。

这基本上有一个原因,在substring(int beginIndex, int endIndex)中,如果beginIndex == endIndex,则结果为空字符串。因此,给定该属性,并且endIndex的最大值是字符串长度,那么应该允许string.substring(string.length(), string.length()),并返回一个空字符串。最后一个可以简化为CCD_ 9。

允许长度作为有效的开始索引还提供了许多不错的属性:

  • "".substring(0)返回""
  • 考虑对String start = string.substring(0, n)String end = string.substring(n)得到以下结果:
    • n = 0:start = ""end = string
    • n = string.length():start = stringend = ""

不允许这样做并引发异常将需要在字符串操作代码中(以及子字符串本身(进行各种额外的边界检查。

  • 公共字符串子字符串(int startIndex(从字符串的startIndex返回子字符串。所以在你的例子中,它将是位置4(它是存在的(,子串将是"0"(空字符串(

最新更新