这取决于您使用的是哪个 JDK 实现。
我做了一些挖掘并找到了实现的方法,public char charAt(int index) 用于 StringBuilder 类。 (注意:我使用的是 Oracle JDK 1.8)。
因此,在这种情况下,StringBuilder 类是AbstractStringBuilder 的子类。这是实现程序员的选择,因为您不会在 docs 中找到它。
我发现charAt 函数是在AbstractStringBuilder 基类上实现的。以下是我系统中相关代码的一些屏幕截图。 (记住,特定的 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
解决cmets的一些问题:
-
[AbstractStringBuilder] 不在文档中,这意味着我们不能用它编写程序?
一个通常跟随另一个。 AbstractStringBuilder 类是 java.lang 包的私有类,这意味着它不能从该包的外部访问。这意味着您将无法在代码中导入和使用此类。这是不属于系统公共 API 的部分代码(在本例中为 JDK 本身)的完美示例,在这种情况下,由于以下几个原因,它不会被记录:
- 你不能使用它
- 实施细节可能会不断变化
- 不应影响公共 API(系统的文档部分)的使用
-
如果StringBuilder 中的charAt() 抛出StringIndexOutOfBoundsException,那么为什么文档只说IndexOutOfBoundsException?
这是因为这是 charAt() 函数基于类的设计意图所描述的行为。由于您可以为异常创建任意数量的子类(就像任何其他不是 final 的 Java 类一样),因此始终由实现程序员来选择从函数中返回(或抛出)的最佳方法,只要功能遵守约定的合同(接口、文档规范、抽象类等)。
话虽如此,您现在可以实现 JDK 并选择您自己的 IndexOutOfBoundsException 子类来抛出这种情况。如果我在我的代码中使用StringBuilder.charAt(),我会捕获文档中描述的异常,因为这将使我获得最大的灵活性/可移植性,而不会冒着因依赖实现细节而中断的风险。关于这个主题已经写了整本书,所以我将把讨论留在这里:总是尝试捕捉你知道可能抛出的最具体的异常,这意味着,如果其他实现可能不会抛出StringOutOfBoundsException,那么你最好只捕获IndexOutOfBoundsException,因为它保证是那种类型(或它的子类)。
更新 2
在这种特定情况下,您几乎可以忽略我上面提到的所有内容,而只关注以下内容:
charAt()是java.lang.CharSequence中描述的接口方法。这意味着对于任何实现类,尝试访问超出序列范围的索引时引发的问题将是IndexOutOfBoundsException。该接口描述了一般行为,并且不必根据String、StringBuilder、AlphabetSoup 或任何其他特定实现来定义此行为。如果那些暗示。决定子类化该异常并在每种情况下提供更具体的错误信息,这很好,但它不会改变一般合同。如果您正在编写通用字符处理系统,那么您可能会写入接口而不关心底层 impl。在这种情况下,您只会知道(或关心)IndexOutOfBoundsException,而不会知道其他任何事情。