Java 字符串索引越界异常
Java String Index Out Of Bounds Exception
是的,我知道如何解决这个问题。我正在查看 String Class 和 String Builder Class 之间的 API。这是我的问题:
StringBuilder sb = new StringBuilder("wibble");
String s = new String("wobble");
sb.charAt(index) //Can throw Index Out Of Bounds Exception
s.charAt(index) //Can throw Index Out of Bounds Exception
sb.substring(start, end) //Can throw STRING index out of bounds exception
s.substring(start, end) //Only throws Index out of Bounds Exception (no String)
所以没有意义的是当它决定抛出 StringIndexOutOfBoundsException 与 IndexOutOfBoundsException 时。是的,我知道 StringIndex 是一个子异常。在 String 和 StringBuilder 中,一些具有相同实现的方法抛出相同的异常,而在一些具有相同实现的方法中,StringBuilder 抛出 sub 异常。那是为什么?
为了避免人们滚动浏览答案,感谢 2 个人的回答,尽管我只能 select 回答一个,他们都帮助澄清了:
Java Oracle 文档人员在 String 的子字符串中输入错误。它应该是 StringIndexOutOfBoundsException。与 StringBuilder
中的 CharAt() 相同
这归结为您正在使用的 JDK 实现。
我做了一些挖掘并找到了实现的方法,public char charAt(int index)
用于 StringBuilder
class。 (注意:我使用的是 Oracle JDK 1.8)。
因此,在这种情况下,StringBuilder
class 是 AbstractStringBuilder
的子 class。这是实施程序员的选择,因为您不会在 docs.
中找到它
我发现 charAt
功能是在 AbstractStringBuilder
基础 class 上实现的。以下是我系统中相关代码的一些屏幕截图。 (记住,具体的 JDK 是 Oracle & Java 1.8)。
更新
我实际上 运行 一些代码来测试抛出哪些异常并发现了一些有趣的东西。我环境中的 charAt()
函数也会抛出 java.lang.StringIndexOutOfBoundsException
。这是我 运行 测试的代码:
public class StringVsStringBuilder {
public static void main(String[] args) {
StringBuilder builder = new StringBuilder("one");
String string = "two";
try {
builder.charAt(10); // Clearly out of bounds
} catch (IndexOutOfBoundsException e) {
System.out.println(String.format(
"Exception encountered accessing character out of index bounds on variable 'builder': %s",
e.getClass()
));
}
try {
string.charAt(10); // Clearly out of bounds
} catch (IndexOutOfBoundsException e) {
System.out.println(String.format(
"Exception encountered accessing character out of index bounds on variable 'string': %s",
e.getClass()
));
}
}
}
这是 运行(Windows 10、64 位,Oracle JDK 1.8.0_191)时的输出:
Exception encountered accessing character out of index bounds on variable 'builder': class java.lang.StringIndexOutOfBoundsException
Exception encountered accessing character out of index bounds on variable 'string': class java.lang.StringIndexOutOfBoundsException
Process finished with exit code 0
解决评论中的一些问题:
[AbstractStringBuilder
] isn't in the docs which means we can't write programs with it?
通常一个接一个。 AbstractStringBuilder
class 对 java.lang
包是私有的,这意味着它不能从该包外部访问。这意味着您将无法在代码中导入和使用此 class。这是不属于系统 public API 一部分的部分代码的完美示例(在这种情况下,JDK 本身),在这种情况下,它不会被记录下来,有几个原因:
- 你不能使用它
- 实施细节可能会不断变化
- 它应该不会影响 public API(系统的文档部分)的使用
if charAt()
in StringBuilder
throws a StringIndexOutOfBoundsException
, then why does the docs say simply IndexOutOfBoundsException
?
这是因为 charAt()
函数的描述行为基于 class 的设计意图。由于您可以为异常创建任意数量的子 classes(就像任何其他 Java class 不是 final
一样),那么它总是由实现程序员决定从函数中选择最适合return(或抛出)的东西,只要该函数遵守商定的契约(接口、文档规范、摘要class等)。
话虽如此,您现在可以实施 JDK 并选择您自己的 IndexOutOfBoundsException
的子 class 来投入此场景。如果我要在我的代码中使用 StringBuilder.charAt()
,我会捕获文档中描述的异常,因为这将允许我最多 flexibility/portability 而不会因依赖实现细节而中断。整本书都是关于这个主题的,所以我将把讨论留在这里:总是尝试捕获你知道可能抛出的最具体的异常,意思是,如果其他实现可能不会抛出 StringOutOfBoundsException
,那么你最好只抓住 IndexOutOfBoundsException
因为它是 gua运行teed 的那种类型(或者它的子class)。
更新 2
在这种特定情况下,您几乎可以忽略我上面提到的所有内容,而只关注以下内容:
charAt()
是java.lang.CharSequence
中描述的接口方法。这意味着对于任何实现 class,当尝试访问超出序列范围的索引时引发的问题将是 IndexOutOfBoundsException
。该接口描述了一般行为,没有必要根据 String
、StringBuilder
、AlphabetSoup
或任何其他特定实现来定义此行为。如果那些意味着。决定 subclass 该异常并在每种情况下提供更具体的错误信息,这很好,但它不会改变一般合同。如果您正在编写一个通用字符处理系统,那么您可能会写入接口而不关心底层实现。在这种情况下,您将只知道(或关心)IndexOutOfBoundsException
而没有别的。
这似乎是文档拼写错误。
在 Java HotSpot(TM) 10.0.1 中,String.substring
会抛出 StringIndexOutOfBoundsException
:
public String substring(int beginIndex, int endIndex) {
int length = length();
checkBoundsBeginEnd(beginIndex, endIndex, length); //here
int subLen = endIndex - beginIndex;
if (beginIndex == 0 && endIndex == length) {
return this;
}
return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen)
: StringUTF16.newString(value, beginIndex, subLen);
}
static void checkBoundsBeginEnd(int begin, int end, int length) {
if (begin < 0 || begin > end || end > length) {
throw new StringIndexOutOfBoundsException(
"begin " + begin + ", end " + end + ", length " + length);
}
}
是的,我知道如何解决这个问题。我正在查看 String Class 和 String Builder Class 之间的 API。这是我的问题:
StringBuilder sb = new StringBuilder("wibble");
String s = new String("wobble");
sb.charAt(index) //Can throw Index Out Of Bounds Exception
s.charAt(index) //Can throw Index Out of Bounds Exception
sb.substring(start, end) //Can throw STRING index out of bounds exception
s.substring(start, end) //Only throws Index out of Bounds Exception (no String)
所以没有意义的是当它决定抛出 StringIndexOutOfBoundsException 与 IndexOutOfBoundsException 时。是的,我知道 StringIndex 是一个子异常。在 String 和 StringBuilder 中,一些具有相同实现的方法抛出相同的异常,而在一些具有相同实现的方法中,StringBuilder 抛出 sub 异常。那是为什么?
为了避免人们滚动浏览答案,感谢 2 个人的回答,尽管我只能 select 回答一个,他们都帮助澄清了: Java Oracle 文档人员在 String 的子字符串中输入错误。它应该是 StringIndexOutOfBoundsException。与 StringBuilder
中的 CharAt() 相同这归结为您正在使用的 JDK 实现。
我做了一些挖掘并找到了实现的方法,public char charAt(int index)
用于 StringBuilder
class。 (注意:我使用的是 Oracle JDK 1.8)。
因此,在这种情况下,StringBuilder
class 是 AbstractStringBuilder
的子 class。这是实施程序员的选择,因为您不会在 docs.
我发现 charAt
功能是在 AbstractStringBuilder
基础 class 上实现的。以下是我系统中相关代码的一些屏幕截图。 (记住,具体的 JDK 是 Oracle & Java 1.8)。
更新
我实际上 运行 一些代码来测试抛出哪些异常并发现了一些有趣的东西。我环境中的 charAt()
函数也会抛出 java.lang.StringIndexOutOfBoundsException
。这是我 运行 测试的代码:
public class StringVsStringBuilder {
public static void main(String[] args) {
StringBuilder builder = new StringBuilder("one");
String string = "two";
try {
builder.charAt(10); // Clearly out of bounds
} catch (IndexOutOfBoundsException e) {
System.out.println(String.format(
"Exception encountered accessing character out of index bounds on variable 'builder': %s",
e.getClass()
));
}
try {
string.charAt(10); // Clearly out of bounds
} catch (IndexOutOfBoundsException e) {
System.out.println(String.format(
"Exception encountered accessing character out of index bounds on variable 'string': %s",
e.getClass()
));
}
}
}
这是 运行(Windows 10、64 位,Oracle JDK 1.8.0_191)时的输出:
Exception encountered accessing character out of index bounds on variable 'builder': class java.lang.StringIndexOutOfBoundsException
Exception encountered accessing character out of index bounds on variable 'string': class java.lang.StringIndexOutOfBoundsException
Process finished with exit code 0
解决评论中的一些问题:
[
AbstractStringBuilder
] isn't in the docs which means we can't write programs with it?通常一个接一个。
AbstractStringBuilder
class 对java.lang
包是私有的,这意味着它不能从该包外部访问。这意味着您将无法在代码中导入和使用此 class。这是不属于系统 public API 一部分的部分代码的完美示例(在这种情况下,JDK 本身),在这种情况下,它不会被记录下来,有几个原因:- 你不能使用它
- 实施细节可能会不断变化
- 它应该不会影响 public API(系统的文档部分)的使用
if
charAt()
inStringBuilder
throws aStringIndexOutOfBoundsException
, then why does the docs say simplyIndexOutOfBoundsException
?这是因为
charAt()
函数的描述行为基于 class 的设计意图。由于您可以为异常创建任意数量的子 classes(就像任何其他 Java class 不是final
一样),那么它总是由实现程序员决定从函数中选择最适合return(或抛出)的东西,只要该函数遵守商定的契约(接口、文档规范、摘要class等)。话虽如此,您现在可以实施 JDK 并选择您自己的
IndexOutOfBoundsException
的子 class 来投入此场景。如果我要在我的代码中使用StringBuilder.charAt()
,我会捕获文档中描述的异常,因为这将允许我最多 flexibility/portability 而不会因依赖实现细节而中断。整本书都是关于这个主题的,所以我将把讨论留在这里:总是尝试捕获你知道可能抛出的最具体的异常,意思是,如果其他实现可能不会抛出StringOutOfBoundsException
,那么你最好只抓住IndexOutOfBoundsException
因为它是 gua运行teed 的那种类型(或者它的子class)。
更新 2
在这种特定情况下,您几乎可以忽略我上面提到的所有内容,而只关注以下内容:
charAt()
是java.lang.CharSequence
中描述的接口方法。这意味着对于任何实现 class,当尝试访问超出序列范围的索引时引发的问题将是 IndexOutOfBoundsException
。该接口描述了一般行为,没有必要根据 String
、StringBuilder
、AlphabetSoup
或任何其他特定实现来定义此行为。如果那些意味着。决定 subclass 该异常并在每种情况下提供更具体的错误信息,这很好,但它不会改变一般合同。如果您正在编写一个通用字符处理系统,那么您可能会写入接口而不关心底层实现。在这种情况下,您将只知道(或关心)IndexOutOfBoundsException
而没有别的。
这似乎是文档拼写错误。
在 Java HotSpot(TM) 10.0.1 中,String.substring
会抛出 StringIndexOutOfBoundsException
:
public String substring(int beginIndex, int endIndex) {
int length = length();
checkBoundsBeginEnd(beginIndex, endIndex, length); //here
int subLen = endIndex - beginIndex;
if (beginIndex == 0 && endIndex == length) {
return this;
}
return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen)
: StringUTF16.newString(value, beginIndex, subLen);
}
static void checkBoundsBeginEnd(int begin, int end, int length) {
if (begin < 0 || begin > end || end > length) {
throw new StringIndexOutOfBoundsException(
"begin " + begin + ", end " + end + ", length " + length);
}
}