考虑以下情况:
String str = "str";
System.out.println("str subs: " + str.substring(3,3));
预期结果:
StringIndexOutOfBoundsException
(因为beginIndex在“字符串结束后”开始)
实际结果:
打印空字符串
来自 String.java :
public String substring(int beginIndex, int endIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
if (endIndex > count) {
throw new StringIndexOutOfBoundsException(endIndex);
}
if (beginIndex > endIndex) {
throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
}
return ((beginIndex == 0) && (endIndex == count)) ? this :
new String(offset + beginIndex, endIndex - beginIndex, value);
}
很容易看出实施没有处理边缘情况,其中:
beginIndex == endIndex == count
(count
是字符串的长度)。
根据 the manual 方法substring:
返回一个新字符串,该字符串是此字符串的子字符串。子串 从指定的beginIndex开始并延伸到at处的字符 index endIndex - 1.因此子字符串的长度是 endIndex的-的beginIndex。
它还声明该方法抛出:
IndexOutOfBoundsException - 如果beginIndex为负数或endIndex 大于此String对象的长度,或者beginIndex是 大于endIndex。
makes sense 是否认为案例:beginIndex == endIndex == count
有效?
我错过了什么吗?
答案 0 :(得分:7)
"abc".substring(3,3) == ""
正如你所说,让我们看一下manual:
返回一个新字符串,该字符串是此字符串的子字符串。
好
子字符串从指定的beginIndex开始,并扩展到索引endIndex的字符 - 1.
无论弦的长度如何,这句话的解释都很困难。但我认为我们可以同意空字符串不会违反这一点。
因此子串的长度是endIndex-beginIndex。
好
抛出:IndexOutOfBoundsException - 如果beginIndex为负数
它不是
或endIndex大于此String对象的长度
它不是
或beginIndex大于endIndex。
不是。
行为似乎是对我的承诺。
你也可以这样看:字符串"abc"
包含四个空子串,两个字符之间,一个在开头,一个在结尾。可以分别通过substring
和1,1
,2,2
和0,0
通过3,3
访问它们。还要与以下代码比较
class EmptyTest {
public static void main (String[] args) {
Matcher m = Pattern.compile("").matcher("abc");
while (m.find()) {
System.out.println(m.start() + "," + m.end());
}
}
}
打印
0,0
1,1
2,2
3,3
答案 1 :(得分:2)
beginIndex == endIndex == count
表示虚拟“开始游标”将紧跟在字符串中的最后一个字符之后,与“结束游标”位于同一点,因此您将获得一个零长度字符串。它似乎与返回(0,0)
的空字符串一样有效。
答案 2 :(得分:0)
此行为与以下内容一致:
String str = "str";
System.out.println("str subs: " + str.substring(2,2));
还返回空字符串而不是子字符串。空集是所有集的子集。
引用类java.lang.String 参数: beginIndex起始索引,包括在内。