String 类中的子字符串方法到达它不应该的索引 [重复]

Posted

技术标签:

【中文标题】String 类中的子字符串方法到达它不应该的索引 [重复]【英文标题】:Substring method in String class reaches the index it isn't supposed to [duplicate] 【发布时间】:2016-02-09 14:32:00 【问题描述】:

如果标题不清楚,我很抱歉。

现在,字符串中的索引从 0 开始。例如:

Index    0   1   2   3   4
String   H   E   L   L   O

在这种情况下,最后一个索引是 4。

如果我尝试做这样的事情:

System.out.println("hello".charAt(5));

它应该抛出一个“索引超出范围异常”。

但是,如果我尝试运行以下代码:

System.out.println("hello".substring(5));

它确实运行了!我写了类似的代码,后来注意到了,无法弄清楚。

最终,问题是我们怎么可能达到这个我们不应该达到的指数?它允许我们写:

stringObj.substring(stringObj.length());

而且它看起来不太安全,因为 stringObj.length() 返回一个比最后一个索引大一的整数。

它是故意制造的吗?这样做有目的吗?如果有,这样做的目的是什么,带来的好处是什么?

【问题讨论】:

【参考方案1】:

当您想到这样的索引时,使用substring 会更容易(就像字母在介于索引之间)

         H E L L O
        0 1 2 3 4 5    <- acceptable range of indexes for "HELLO"
        ^         ^
        |         |
      start      end = length
   (min index) (max index)

当您从startend 子串时,您只会得到这些索引之间的字符。

所以在"HELLO".substring(2,4)的情况下你会得到一部分

 L L 
2 3 4

返回"LL"

现在在substring(5) 的情况下,它的作用与substring(5,length) 相同,这意味着在这种情况下它是substring(5,5)。因此,由于 5 索引 exists 在我们的“模型”中作为可接受的值,并且由于 55 之间没有字符,因此我们得到空字符串。

只要我们的模型可以接受索引,substring(0,0)substring(1,1) 等也会发生类似情况。

StringIndexOutOfBoundsException 仅在我们尝试访问不可接受的索引时发生,这意味着:

负面的:-1, -2, ... 大于length。这里:67,...

【讨论】:

【参考方案2】:

由于“索引越界异常”而无法编译,

它确实编译。当您尝试执行代码时会收到运行时异常。

System.out.println("hello".substring(5));

最终,问题是我们怎么可能达到这个我们不应该达到的索引?

阅读substring(...) 方法的API。它解释了方法的工作原理以及参数的含义。

在这种情况下,它返回一个空字符串。

【讨论】:

我们不会在 "hello".substring(5) 上得到异常 但是 API 解释说我们得到 "emptiness".substring(9) 返回 "" (一个空字符串)docs.oracle.com/javase/7/docs/api/java/lang/… 是的,我也检查了文档。但我不明白它说 beginIndex 是包容性的。他们是如何实现这样的方法的? it says beginIndex is inclusive - 当然是包容性的。您将如何获得索引为 0 的第一个字符?你会指定-1吗?那没有意义。将 substring() 方法与 indexof() 方法结合使用也很容易。您使用 indexof() 获取索引,使用 substring() 获取索引中的所有字符。 我明白它应该是包容性的,但我仍然不明白为什么当你尝试 str.substring(str.length()); 时它不会抛出异常; I still don't get why it doesn't throw an exception API 特别声明它将返回一个空字符串。 API 明确指出,如果索引大于长度,它将抛出异常。所以这种行为是有据可查的。就个人而言,我想不出为什么我想使用 substring 返回一个空字符串。【参考方案3】:

参考Java String API中的substring方法 (http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#substring(int))

String ".length()" 方法将返回字符串中的字符数。

如果你从 0->4 数 "HELLO",它仍然是 5 个字符(长度),也就是调用 "Hello".length() 时返回的数字。

如果要访问字符串的最后一个字符,请使用 (Stringobj.length()-1);通过使用 .length() 或 .size() 方法调用来访问 String 或 Array 的最后一个元素在 Java 中是标准化的。

【讨论】:

【参考方案4】:

在这种情况下,了解方法 charAt 和 substring 的实现细节很有帮助。

this tutorial 中描述的 charAt 可以描述为:

返回位于字符串指定索引处的字符。字符串索引从零开始。

这就是为什么调用:

System.out.println("hello".charAt(5));

给了

Exception in thread "main" java.lang.StringIndexOutOfBoundsException:
String index out of range: 5

因为正如您完美描述的那样,最大索引只有 4。

substring 在 java 文档中进行了描述,并在“示例”部分解释了您的确切情况 here,其中指出:

"emptiness".substring(9) 返回 ""(一个空字符串)

更多参考,这里是java's substring(int index)实现的源代码,你可以看到它使用了java的substring(int beginInndex, int endIndex)方法。

【讨论】:

以上是关于String 类中的子字符串方法到达它不应该的索引 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

字符串类中的Object的equals方法和自定义类中的Object的equal方法之间有什么区别

类中的String,StringBuffer,冒泡排序

Java基础面试:一文看懂String类中的常用方法

Java基础面试:一文看懂String类中的常用方法

String类的substring()方法

c#中Array类中的常用方法的功能