Java 字符串索引越界异常

标签 java string exception indexoutofboundsexception stringbuilder

是的,我知道如何解决这个问题。我正在查看 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 是一个子异常(exception)。在 String 和 StringBuilder 中,某些实现相同的方法会抛出相同的异常,而在某些实现相同的方法中,StringBuilder 会抛出子异常。那为什么呢?

为了避免人们滚动浏览答案,并感谢回答的 2 个人,即使我只能选择一个作为回答,两者都有助于澄清:
Java Oracle Doc People 在 String 的子字符串中打错字。它应该是 StringIndexOutOfBoundsException。与 StringBuilder 中的 CharAt() 相同

最佳答案

这取决于您使用的是哪个 JDK 实现。

我做了一些挖掘,找到了实现的方法,public char charAt(int index)对于StringBuilder类(class)。 (注意:我使用的是 Oracle JDK 1.8)。

因此,在这种情况下,StringBuilder类是 AbstractStringBuilder 的子类.这是实现程序员的选择,因为您不会在 docs 中找到它。 .

我找到了 charAt功能在 AbstractStringBuilder 上实现基类。以下是我系统中相关代码的一些屏幕截图。 (请记住,特定的 JDK 是 Oracle 和 Java 1.8)。

enter image description here

enter image description here

更新

我实际上运行了一些代码来测试抛出了哪些异常并发现了一些有趣的东西。 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类是 java.lang 私有(private)的包,这意味着它不能从该包的外部访问。这意味着您将无法在代码中导入和使用此类。这是不属于系统公共(public) API(在本例中为 JDK 本身)的部分代码的完美示例,在这种情况下,将不会记录它,原因如下:
  • 你不能使用它
  • 实现细节可能会不断变化
  • 它不应该影响公共(public) API 的使用(系统的文档部分)
  • if charAt() in StringBuilder throws a StringIndexOutOfBoundsException, then why does the docs say simply IndexOutOfBoundsException?



    这是因为这是 charAt() 所描述的行为。基于类的设计意图的功能。由于您可以为异常创建任意数量的子类(就像任何其他不是 final 的 Java 类一样),所以始终由实现程序员来选择从函数中返回(或抛出)的最佳方法,只要功能遵守约定的契约(Contract)(接口(interface)、文档规范、抽象类等)。

    话虽如此,您现在可以实现 JDK 并选择您自己的 IndexOutOfBoundsException 子类扔在这种情况下。如果我使用 StringBuilder.charAt()在我的代码中,我会捕获文档中描述的异常,因为这将使我获得最大的灵 active /可移植性,而不会冒因依赖实现细节而中断的风险。关于这个主题已经写了整本书,所以我将在这里留下讨论:始终 try catch 您知道可能抛出的最具体的异常,这意味着,如果其他实现可能不会抛出 StringOutOfBoundsException ,那么你最好只抓到 IndexOutOfBoundsException因为它保证是那种类型(或它的子类)。

  • 更新 2

    在这种特定情况下,您几乎可以忽略我上面提到的所有内容,而只关注以下内容:
    charAt() java.lang.CharSequence 中描述的接口(interface)方法.这意味着对于任何实现类,尝试访问超出序列范围的索引时引发的问题将是 IndexOutOfBoundsException .该接口(interface)描述了一般行为,并且没有必要根据 String 来定义此行为。 , 一个 StringBuilder , 一个 AlphabetSoup或任何其他具体实现。如果那些暗示。决定对该异常进行子类化并在每种情况下提供更具体的错误信息,这很好,但它不会改变一般契约(Contract)。如果您正在编写通用字符处理系统,那么您可能会写入接口(interface)而不关心底层 impl。在这种情况下,您只会知道(或关心)IndexOutOfBoundsException没有别的了。

    关于Java 字符串索引越界异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55105508/

    相关文章:

    r - 用于字符向量时匹配与魅力匹配

    c - 在C中分割字符串并分别获取每个字段

    c++ - std::vector<>::emplace_back() 中的异常安全吗?

    java - 在 Java 中可以绝对保证死锁吗?

    java - 鸭子类型(duck typing)和泛型编程

    php - 检查整个字符串是否包含相同的字符

    android - 应用程序中的奇怪异常

    Python:为什么 __getattr__ 会捕获 AttributeErrors?

    java - zeromq 与 Python 与 Java 的 node.js 性能

    java - Android登录界面-内容已被消费