来自JavaDoc
java.lang 类StringIndexOutOfBoundsException
由 String 方法抛出以指示索引为负数或大于字符串的大小。对于某些方法,例如 charAt 方法,当索引等于字符串的大小时也会引发此异常。
您超出了字符串的长度。
另外我认为你的逻辑有一些错误(见下文)。
你真正想做的是:
while ((k < s.length()) && (j < s.length())) { // While no String goes out of Bounds
if (s.charAt(j) != s.charAt(k)) { // If we get a different character
break; // Get out of the loop
} else {
j++; // Advance one position
k++;
}
}
你在做什么是这样的:
if (s.charAt(j) == s.charAt(k)) { // If the characters are equal
while ((s.charAt(j) == s.charAt(k)) // While the characters are equal
&& (k < s.length()) && (j < s.length())) { // And the position is smaller than the length
j++;
k++;
}
count += j;
}
If 是多余的,因为无论如何您都会在 while 中检查它,并且 count 将增加零。
但更重要的是,在 while 的终止条件下,您的 check ifs.charAt(j)
发生在 check 之前j < s.length()
。因此,在您查看 j 是否过大之前,您会在第一种情况下遇到异常
此外,由于表达式是 Java 是从左到右计算的,因此您可以像这样更改循环:
while ((k < s.length()) && (j < s.length()) && (s.charAt(j) == s.charAt(k))) {
j++;
k++;
}
现在你没有得到一个异常,因为如果前两个术语是假的(从左边开始),那么右边的另外两个术语根本不会被评估(至少在我的 JVM 中)
输出:
run:
2
ababaa
aa
11
3
希望有帮助。
ps:我也换了行
int t = se.nextInt();
到
int t = se.nextInt();se.nextLine();
这样您就可以在给出数字后解析换行符。
澄清
1) 为什么se.nextLine()
你有过
int t = se.nextInt();
假设用户输入23
并按下 enter,这意味着InputSream将从键盘读取23\n
。23
是用户输入的数字,\n
是换行符。使用换行符是为了让计算机知道一行何时结束,下一行何时开始,并在用户按下回车时自动插入。此处提供更多信息:如何获得依赖于平台的换行符?
当您呼叫 时nextInt()
,您只会读取输入的号码,但不会读取\n
字符。因此,下次您调用 时readLine()
,您将读取\n
输入号码(并按下回车键)时剩下的内容。这就是您将上述命令更改为的原因
int t = se.nextInt();se.nextLine();
现在您读取了那个额外的\n
字符,当您读取用户输入的字符串时,下一次调用nextLine()
将正确返回该字符串。
2)为什么将循环更改为((k < s.length()) && (j < s.length()) && (s.charAt(j) == s.charAt(k))
你有这个
( (s.charAt(j)==s.charAt(k)) && (k<s.length()) && (j<s.length()) )
这导致了StringIndexOutOfBoundsException。这就是为什么:
在 Java 中,表达式是从左到右计算的。这意味着,在每次迭代中,JVM 将首先检查(s.charAt(j)==s.charAt(k))
. 如果这个词是真的,那么它会评估这个词(k<s.length())
,如果这也是真的,它会评估(j<s.length())
。如果所有这些条件都为真,程序将进入循环。
另一方面,如果第一项(即(s.charAt(j)==s.charAt(k))
)为假,则整个表达式为假(因为我们有AND运算符),并且不需要计算其余项。
现在,为什么会导致Exception?看看最后一次迭代发生了什么。此时,变量j
(或k
等效)将具有等于 string 长度的值s
。当 JVM 试图评估终止条件时,它会首先评估 term (s.charAt(j)==s.charAt(k))
。由于j
等于 的长度s
,因此调用charAt()
将抛出StringIndexOutOfBoundsException,因为调用将尝试获取字符串之外的字符。请记住,字符串中的索引是 from 0
to length() - 1
。这是您获得异常的地方。
但是,如果您将终止条件更改为
((k < s.length()) && (j < s.length()) && (s.charAt(j) == s.charAt(k)))
您将避免StringIndexOutOfBoundsException。这就是为什么。这一次,术语(k < s.length())
和 在调用之前(j < s.length())
被评估。因此,当我们到达字符串的末尾时,前两个项中至少有一个是,并且不需要计算表达式的其余部分。因此,在最后一次迭代中,该方法根本没有被调用,所以我们没有得到异常。charAt()
false
charAt
我希望这能稍微澄清一下情况。