为什么'substring(startIndex,endIndex)'不会抛出“超出范围”

时间:2010-07-13 00:36:34

标签: java substring

在Java中我使用的是substring()方法,我不确定为什么它没有抛出“索引之外”错误。

字符串abcde的索引从0开始到4,但substring()方法将startIndex和endIndex作为参数,基于我可以调用foo.substring(0)并获取“abcde”的事实”

那么为什么子串(5)有效呢?该指数应该超出范围。解释是什么?

/*
1234
abcde
*/
String foo = "abcde";
System.out.println(foo.substring(0));
System.out.println(foo.substring(1));
System.out.println(foo.substring(2));
System.out.println(foo.substring(3));
System.out.println(foo.substring(4));
System.out.println(foo.substring(5));

此代码输出:

abcde
bcde
cde
de
e
     //foo.substring(5) output nothing here, isn't this out of range?

当我用6代替5:

foo.substring(6)

然后我收到错误:

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

6 个答案:

答案 0 :(得分:21)

根据Java API doc,当起始索引大于字符串的 Length 时,子字符串会引发错误。

  

IndexOutOfBoundsException - 如果   beginIndex为负数或大于   这个String对象的长度。

事实上,他们举了一个像你的例子:

"emptiness".substring(9) returns "" (an empty string)

我想这意味着最好将Java String视为以下内容,其中索引包含在|中:

|0| A |1| B |2| C |3| D |4| E |5|

也就是说字符串同时包含起始索引和结束索引。

答案 1 :(得分:15)

当你执行foo.substring(5)时,它会从“e”之后的位置开始并从字符串末尾开始获取子字符串。顺便提一下,开始和结束位置恰好相同。因此,空字符串。您可以将索引视为字符串中的实际字符,而不是字符之间的位置。

        ---------------------
String: | a | b | c | d | e |
        ---------------------
Index:  0   1   2   3   4   5

答案 2 :(得分:3)

这是因为substring函数返回一个“包含”子字符串。因此,索引5指向字符串结尾之前的位置,但是在字符串的最后一个显示字符之后。

这在文档中显示: http://download.oracle.com/docs/cd/E17476_01/javase/1.4.2/docs/api/java/lang/String.html#substring(int)

答案 3 :(得分:3)

来自String API javadoc:

public String substring(int beginIndex)
    Returns a new string that is a substring of this 
    string. The substring begins with the "" character 
    at the specified index and extends to the end of this string.

public String substring(int beginIndex, int endIndex)
    Returns a new string that is a substring of this 
    string. The substring begins at the specified beginIndex 
    and extends to the character at index endIndex - 1. Thus 
    the length of the substring is endIndex-beginIndex.

示例:

"unhappy".substring(2) returns "happy" 
"Harbison".substring(3) returns "bison"
"emptiness".substring(9) returns "" (an empty string)

"hamburger".substring(4, 8) returns "urge"
"smiles".substring(1, 5) returns "mile"

参数:

beginIndex - the beginning index, inclusive.
Returns:
the specified substring.
Throws:
IndexOutOfBoundsException - if beginIndex is negative or 
larger than the length of this String object.

====

所以这是设计的。如果将索引作为字符串的大小,则返回空字符串。

答案 4 :(得分:3)

我知道这个帖子很老了,但这是一个基本问题,我认为这值得澄清。

问题是适当的。我将此视为Java String.substring(int beginIndex,int endIndex)方法中的软件错误。

http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#substring%28int,%20int%29

来自Java文档https://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html

Java Arrays

Java / C / C ++和我所知道的所有其他语言都不会将数组索引视为' divider'数组元素之间。

参数:     beginIndex - 起始索引,包括。     endIndex - 结束索引,独占。

endIndex的名称错误,因为该语言不允许内存访问endIndex + 1中的地址,这是包含最后一个数组元素或者endIndex错误定义所必需的,并且必须是:      endIndex - 结束索引,包括。

最可能的情况是第二个参数被错误命名。它应该是:      length - 从beginIndex开始所需的字符串长度。

我们知道Gosling基于C / C ++语言的Java语法是为了熟悉。从C +++字符串类http://www.cplusplus.com/reference/string/string/substr/我们看到方法定义是:

string substr(size_t pos = 0,size_t len = npos)const;

请注意,方法定义中的第二个参数是' len'长度。

LEN     要包含在子字符串中的字符数(如果字符串更短,则使用尽可能多的字符)。

testString有10个字符,索引位置为0到9.指定endIndex为10应始终抛出IndexOutOfBoundsException(),因为testString没有endIndex为10.

如果我们使用查看C ++方法的具体值来测试JUnit中的方法,我们期望:

String testString =" testString&#34 ;; assertThat(testString.substring(4,6),equalTo(" String"));

但当然我们得到了预期:" String"但是" St"

从索引0到char' g'的testString的长度in' String'是10个字符。 如果我们使用10作为' endIndex'参数,

String testString =" testString&#34 ;; assertThat(testString.substring(4,10),equalTo(" String"));

"通行证"来自JUnit。

如果我们将参数2重命名为" lengthOfSubstringFromIndex0"你不必执行endIndex - 1计数,并且它永远不会抛出指定endIndex 10时所期望的IndexOutOfBoundsException(),它超出了底层数组的范围。 http://docs.oracle.com/javase/7/docs/api/java/lang/IndexOutOfBoundsException.html

这只是你必须记住这种方法特质的那一次。第二个参数未正确命名。 Java方法签名应为:

public String substring(int beginIndex,
           int lengthOfSubstringFromIndex0)

或重新定义方法以匹配C ++ string :: substr方法。重新定义当然意味着重写整个互联网,所以它不太可能。

答案 5 :(得分:2)

substring(5)指向现有索引...它恰好指向一个空字符串。另一方面,substring(6)只是疯狂的谈话。 :)