Почему вызов подстроки, использующей длину строки в качестве начального индекса, не вызывает исключение OutOfBoundsException?

#java

Вопрос:

Когда я тестировал какой-то код, я заметил, что метод подстроки не создавал бы исключения, если бы индекс, который я использовал, был равен длине строки. Например:

 String s = "holy";
System.out.println(s.substring(4));
 

Вывод ничего не вернет, но не вызовет исключения. Но если бы я попытался позвонить:

 String s = "holy";
System.out.println(s.substring(5));
 

Это вызовет исключение IndexOutOfBoundsException. Я прочитал Javadoc для этого метода, и в нем говорится

если beginIndex отрицателен или больше длины этого строкового объекта.

Кто-нибудь знает, почему это позволяет, чтобы начальный индекс был равен длине строки?

Ответ №1:

Подумайте о других призывах substring :

 "holy".substring(n)
 

может быть визуализировано как копирование диапазона символов между n (включительно) и концом строки (эксклюзивно).

Например:

 "holy".substring(0)`

 h o l y
O-------X    (O = start, X = end)
0 1 2 3 4
 

То есть начальная позиция находится непосредственно перед символом, а конечная позиция-сразу после символа. Результирующая длина строки end - start в данном случае равна 4.

и

 "holy".substring(1)

 h o l y
  O-----X     // length = 4 - 1 = 3.
0 1 2 3 4
 

и т.д. Затем:

 "holy".substring(4)
 

может быть визуализирован как

  h o l y
        O     // O and X are at the same position
        X     // length = 4 - 4 = 0
0 1 2 3 4
 

Хорошо, что O и X находятся в одной и той же позиции: это просто означает, что результатом является строка нулевой длины, "" .

Но увеличьте индекс до 5:

 "holy".substring(5)

 h o l y
        X-O    // O is after X
               // length = 4 - 5 = -1 (?!)
0 1 2 3 4 5
 

Строка длиной -1 не имеет смысла, отсюда и исключение.

Комментарии:

1. Спасибо, визуализация очень помогла, и теперь это имеет смысл

Ответ №2:

  • общедоступная строковая подстрока(int startIndex) возвращает подстроку из начального индекса вашей строки. Таким образом, в вашем примере это будет позиция 4 (которая существует), а подстрока будет «» (пустая строка).

Комментарии:

1. Что на самом деле происходит «под капотом»? Позиция 4 технически находится за пределами диапазона индексов строки, так как же можно что-то вернуть, не выдав ошибку?

Ответ №3:

В принципе, для этого есть одна причина substring(int beginIndex, int endIndex) , если в beginIndex == endIndex результате получается пустая строка. Таким образом, учитывая это свойство и тот факт, что максимальное значение endIndex равно длине строки, то разрешение string.substring(string.length(), string.length()) должно быть разрешено и также возвращать пустую строку. И это последнее можно упростить до string.substring(string.length()) .

Разрешение длины в качестве допустимого начального индекса также обеспечивает ряд приятных свойств:

  • "".substring(0) ВОЗВРАТ ""
  • Рассматривая пары String start = string.substring(0, n) и String end = string.substring(n) результаты в следующем:
    • n = 0 : start = "" , end = string
    • n = string.length() : start = string , end = ""

Запрещение этого и создание исключения потребовало бы всех видов дополнительных проверок границ в коде обработки строк (и в самой подстроке, если на то пошло).