在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
答案 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指向字符串结尾之前的位置,但是在字符串的最后一个显示字符之后。
答案 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 / 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)只是疯狂的谈话。 :)