Почему String.indexOf не использует исключение, но возвращает -1, когда подстрока не найдена?

Почему String.indexOf не использует исключение, но возвращает -1, если подстрока не найдена?

Цель этого вопроса: при запуске настраиваемого исключения.

Я считаю, что избежать необходимости возвращать специальный код ошибки - это правильный путь проектирования.

Каково ваше мнение?

Ответ 1

Как правило, если целью метода является проверка чего-либо, то отсутствие этого не должно быть исключением. Если метод предполагает, что что-то истинно, то отсутствие чего-то будет исключением. Таким образом, "File.exists()" не генерирует исключение FileNotFoundException, но "File.open()" делает.

Ответ 2

исключения относятся к исключительным случаям, когда строка не содержит буквы, что вряд ли является исключительным, если вы не используете ее для какого-либо экстремального случая. Если это то, что вы делаете, вы всегда можете выбрать свое собственное исключение.

Ответ 3

Последнее, что я слышал об этом, было...

'Вы делаете исключение, когда метод не может сделать то, что он promises to '- Джефф Рихтер CVC 2nd ed

  • IndexOf() promises вы должны вернуть индекс первого вхождения строки char/. Это могло бы вызвать исключение, если бы по какой-то причине оно не могло выполнить свою работу. Он выполнил свою работу, но не нашел строку и, следовательно, возвращает -1, чтобы передать не найденный результат.
  • File.Open() будет генерировать FileNotException для несуществующего пути к файлу, поскольку он не может выполнить то, что он promises.. i.e открыть указанный файл.

Ответ 4

return -1 почти столь же ужасен, как и выброс исключения. Правильный способ - использовать тип опции, если язык просто лучше ее поддерживает. В нормальной ситуации, когда есть результат, вы завершаете результат в объект и возвращаете его. В противном случае вы возвращаете объект, представляющий ситуацию "не результат".

На сайте вызова вам нужно проверить, какой из них был; вы не можете просто использовать возвращаемое значение из-за своего супер-типа, их нужно проверять с помощью сопоставления с образцом.

В псевдо синтаксисе:

class Option[a] = Some[a] | None,

где a - общий тип типа, Some представляет результат со значением и None non-result без значения.

в indexOf случае у вас будет:

Option[Integer] indexOf(char c) = {
   if(found) return Some(index)
   else return None
}

и вы используете это следующим образом:

result = "uncle".indexOf('c')
result match {
  Some(i) => System.out.println("index was: " + i);
  None => System.out.println("no value");
}

Если вы опустили либо Some, либо None из соответствия (который является обобщенным ключом), компилятор выдаст вам предупреждение.

Ответ 5

Намного легче справиться с проверкой на -1, чем нахождение исключения.

Ответ 6

Также потому, что исключения являются дорогостоящими с точки зрения производительности

Ответ 7

Помимо аргументов против исключений вообще, я бы добавил, что -1 может быть полезным результатом от indexOf и lastIndexOf, а не только от специального значения. Например, чтобы проанализировать имя файла из строки, которая может содержать или не содержать путь:

String filename = arg.substring(arg.lastIndexOf('/') + 1);

Хотя, возможно, надуманный пример, это будет немного более громоздким с исключениями.

Ответ 8

Здесь много хороших ответов. Это проблема дизайна, где прагматизм имеет приоритет над следующими "правилами". В этом случае существуют некоторые противоречивые "правила":

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

против.

  • не бросать исключения во время рутинного выполнения кода, только когда произойдет что-то неожиданное

Я согласен с этим проектным решением. Однако, если вы этого не сделаете, вы всегда можете написать свой собственный код, чтобы проверить наличие строки перед проверкой индекса. Не будьте узником своего языка, согните его по своему усмотрению. Языки должны быть подвергнуты пыткам!

Ответ 9

Я думаю, что нужно выбросить исключение, когда произойдет что-то неожиданное. Тем не менее, подстрока, не найденная в String, не такая неожиданная, может случиться, это разумный результат.

Я согласен с вами в том, что нужно избегать возврата кодов ошибок, но в этом случае у нас есть только два варианта: найденная строка или строка не найдены.

Ответ 10

Пока автор Java string.indexOf не сообщит нам историю...

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

  • indexOf должен возвращать числовое значение, так что, когда совпадение найдено, вы знаете, где оно
  • действительные индексы гарантированно будут всегда целыми числами Индексы
  • array (и string) основаны на нулевом значении в Java
  • Java строго типизирован
  • целочисленные числовые типы заключены в Java

Учитывая эти основные ограничения, некоторые возможные варианты для возвращаемого типа функции будут целочисленными (в идеале от типа, достаточно большого для представления последнего индекса в наибольшей возможной строке), OR... Object (и, возможно, возврата null для указания не найден). Но на практике возвращение Object не было бы ни эффективным, ни удобным для пользователя из-за необходимости проверять его достоверность и отличать до использования для найденного случая - так что это действительно не жизнеспособный вариант!

Итак, отпустите целое число. Мы хотим выбросить исключение, если не нашли? У исключений бросания есть несколько собственных проблем - создание объектов исключения и переключение на обработчики исключений могут быть весьма неэффективными, а писать блоки try/catch вокруг вызовов indexOf тоже не забавно!

Итак, скажем, мы сузили его: он должен вернуть (подписанный) целочисленный тип, а не исключать исключение. Теперь какое целочисленное значение следует вернуть, чтобы оно не было найдено?

Чтобы разрешить поиск в строках как можно больше, мы должны зарезервировать все положительные целые числа для использования по мере успешного использования. И наоборот, ни один из отрицательных чисел не требуется для представления индекса "найденного", поэтому все потенциально доступны для использования в качестве кодов возврата, представляющих "не найденные".

Если бы мы могли выбрать любое отрицательное число, чтобы представить не найденное, или просто сказали, что "все отрицательные значения возврата означают не найденные", это выполнит эту работу... Но будет ли это лучший дизайн?

Каковы некоторые причины использовать -1 вместо других отрицательных чисел? Мои любимые причины просто "-1 легко запомнить для всех, и вы можете делать точные тесты равенства". (Вместо того, чтобы быть вынужденным использовать неравенства и думать об отдельных проблемах, например о том, хотите ли вы меньше или меньше или равно, и какое значение сравнить с нулевым или отрицательным)

Я также иногда восхищаюсь причиной Криса, что (перефразируя) "он отлично работает с substring(foundIndex + 1)".