为了账号安全,请及时绑定邮箱和手机立即绑定

Java 字符串索引越界异常

Java 字符串索引越界异常

扬帆大鱼 2022-08-03 10:09:19
是的,我知道如何解决这个问题。我正在研究字符串类和字符串生成器类之间的API。以下是我的问题:StringBuilder sb = new StringBuilder("wibble");String s = new String("wobble");sb.charAt(index) //Can throw Index Out Of Bounds Exceptions.charAt(index) //Can throw Index Out of Bounds Exceptionsb.substring(start, end) //Can throw STRING index out of bounds exceptions.substring(start, end) //Only throws Index out of Bounds Exception (no String)因此,当它决定抛出StringIndexOutOfBoundsException与IndexOutOfBoundsException时,没有意义。是的,我知道StringIndex是一个子例外。在 String 和 StringBuilder 中,某些具有相同实现的方法会引发相同的异常,而在某些具有相同实现的方法中,StringBuilder 会引发 sub 异常。这是为什么呢?为了节省人们滚动浏览答案的时间,并感谢2个人回答,即使我只能选择一个作为答案,两者都有助于澄清:Java Oracle Doc People在String的子字符串中打错了。它应该是StringIndexOutOfBoundsException。与 StringBuilder 中的 CharAt() 相同
查看完整描述

2 回答

?
幕布斯6054654

TA贡献1876条经验 获得超7个赞

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

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

因此,在本例中,该类是 的子类。这是实现程序员的选择,因为你不会在文档中找到它。StringBuilderAbstractStringBuilder

我发现该函数是在基类上实现的。以下是来自我的系统的相关代码的一些屏幕截图。(请记住,特定的JDK是Oracle和Java 1.8)。charAtAbstractStringBuilder


//img1.sycdn.imooc.com//62e9d8eb000112df04010101.jpg

//img1.sycdn.imooc.com//62e9d8f30001305908010425.jpg

更新

我实际上运行了一些代码来测试抛出的异常,并发现了一些有趣的东西。我的环境中的函数还抛出了一个 .以下是我运行以测试它的代码: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,64bit,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]不在文档中,这意味着我们不能用它编写程序?

    一个通常跟随另一个。该类是包的私有类,这意味着无法从该包的外部访问它。这意味着您将无法在代码中导入和使用此类。这是一个完美的例子,说明某些不属于系统公共API的代码部分(在本例中是JDK本身),在这种情况下,由于以下几个原因,它不会被记录:AbstractStringBuilderjava.lang

    1. 您不能使用它

    2. 实施细节可能会不断变化

    3. 它不应影响公共API(系统的记录部分)的使用

  • 如果在抛出一个,那么为什么文档说简单?charAt()StringBuilderStringIndexOutOfBoundsExceptionIndexOutOfBoundsException

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

    话虽如此,您现在可以实现JDK,并选择自己的子类来投放此场景。如果我在我的代码中使用,我会捕获文档中描述的异常,因为这将允许我获得最大的灵活性/可移植性,而不会因依赖实现细节而中断风险。关于这个主题已经写了整本书,所以我将把讨论留在这里:总是尝试捕捉你知道可能被抛出的最具体的异常,这意味着,如果其他实现可能不会抛出,那么你最好抓住,因为它保证是该类型(或它的子类)。IndexOutOfBoundsExceptionStringBuilder.charAt()StringOutOfBoundsExceptionIndexOutOfBoundsException

更新 2

在这种特定情况下,您几乎可以忽略我上面提到的所有内容,而只关注以下内容:

charAt()是 java.lang.CharSequence 中描述的一种接口方法。这意味着对于任何实现类,当尝试访问超出序列边界的索引时,引发的问题将是 .该接口描述了一般行为,并且没有必要用 、 a 、 an 或任何其他特定实现来定义此行为。如果这些暗示。决定对该异常进行子类化,并在每种情况下提供更具体的错误信息,这很好,但它不会更改总协定。如果您正在编写通用字符处理系统,那么您可能会写入接口而不关心底层 impl。在这种情况下,你只会知道(或关心)什么都没有。IndexOutOfBoundsExceptionStringStringBuilderAlphabetSoupIndexOutOfBoundsException


查看完整回答
反对 回复 2022-08-03
?
绝地无双

TA贡献1946条经验 获得超4个赞

这似乎是一个文档拼写错误。


在 Java HotSpot(TM) 10.0.1 中,确实抛出了 :String.substringStringIndexOutOfBoundsException


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);

    }

}


查看完整回答
反对 回复 2022-08-03
  • 2 回答
  • 0 关注
  • 97 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信