Исключение за пределами списка Java-строк - PullRequest
4 голосов
/ 11 марта 2019

Да, я знаю, как это исправить.Я смотрел на API между String Class и String Builder Class.Вот что я спрашиваю:

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.Так почему же это так?

Чтобы спасти людей, прокручивающих ответы, и благодаря двум ответившим, хотя я могу выбрать только один ответ, оба помогли уточнить: Java Oracle Doc People сделал опечатку в подстроке дляСтрока.Предполагается, что это StringIndexOutOfBoundsException.То же самое с CharAt () в StringBuilder

Ответы [ 2 ]

1 голос
/ 11 марта 2019

Кажется, это опечатка документа.

В 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);
    }
}
1 голос
/ 11 марта 2019

Это зависит от того, какую реализацию JDK вы используете.

Я немного покопался и нашел реализованный метод public char charAt(int index) для класса StringBuilder.( Примечание: я использую Oracle JDK 1.8 ).

Итак, в этом случае класс StringBuilder является подклассом AbstractStringBuilder.Это выбор программиста-разработчика, поскольку вы не найдете его в документах .

Я обнаружил, что функция 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] нет в документации, что означает, что мы не можем писать программы с ним?

    Один обычно следует за другим.Класс AbstractStringBuilder является закрытым для пакета java.lang, что означает, что к нему нельзя получить доступ извне этого пакета.Это означает, что вы не сможете импортировать и использовать этот класс в своем коде.Это прекрасный пример некоторой части кода, которая не является частью общедоступного API системы (в данном случае, самого JDK), и в этом случае она не будет документирована по нескольким причинам:

    1. Вы не можете его использовать
    2. Детали реализации могут постоянно меняться
    3. Это не должно влиять на использование общедоступного API (документированной части системы)
  • если charAt() в StringBuilder выдает StringIndexOutOfBoundsException, то почему в документах просто говорится: IndexOutOfBoundsException?

    Это потому, чтоописанное поведение функции charAt(), основанное на замысле класса.Так как вы можете создать любое количество подклассов для исключений (как и любой другой класс Java, который не является final), то программист-исполнитель всегда должен выбрать, что лучше всего возвращать (или выбрасывать) из функции,до тех пор, пока функция придерживается согласованного контракта (интерфейс, спецификация документа, абстрактный класс и т. д.).

    Сказав это, вы можете реализовать JDK прямо сейчас и выбрать свой собственный подкласс IndexOutOfBoundsExceptionбросить в этом сценарии.Если бы я использовал StringBuilder.charAt() в своем коде, я бы поймал исключение, описанное в документации, потому что это позволило бы мне максимально гибко / переносимо, не рискуя перерывом, полагаться на детали реализации.На эту тему написаны целые книги, поэтому я оставлю обсуждение здесь: всегда старайтесь поймать самое конкретное исключение, которое, как вы знаете, может быть сгенерировано, то есть, если возможно, что другие реализации могут не выдавать StringOutOfBoundsException, тогда вылучше поймать только IndexOutOfBoundsException, поскольку он гарантированно относится к этому типу (или его подклассу).

Обновление 2

В этом конкретном случае выможет в значительной степени игнорировать все, что я упомянул выше, и сосредоточиться на следующем:

charAt() - метод интерфейса, описанный в java.lang.CharSequence.Это означает, что для любого реализующего класса проблема, возникающая при попытке доступа к индексу за пределами последовательности, будет IndexOutOfBoundsException.Интерфейс описывает общее поведение, и нет необходимости определять это поведение в терминах String, StringBuilder, AlphabetSoup или любой другой конкретной реализации.Если это подразумевает.решите создать подкласс этого исключения и дать более конкретную информацию об ошибках в каждом случае, это нормально, но это не меняет общий договор.Если вы пишете общую систему обработки символов, то вы, скорее всего, будете писать в интерфейс и не заботиться о лежащем в основе значении.В этом случае вы будете знать (или заботиться) только о IndexOutOfBoundsException и больше ничего.

...