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

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

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

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

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

Ответы [ 10 ]

29 голосов
/ 13 мая 2009

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

18 голосов
/ 13 мая 2009

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

16 голосов
/ 13 мая 2009

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

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

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

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

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

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

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

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

в 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 (что-то вроде обобщенного переключателя), компилятор выдаст вам предупреждение.

3 голосов
/ 13 мая 2009

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

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

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

3 голосов
/ 13 мая 2009

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

3 голосов
/ 13 мая 2009

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

2 голосов
/ 13 мая 2009

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

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

против

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

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

1 голос
/ 13 мая 2009

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

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

0 голосов
/ 07 ноября 2017

Пока автор Java string.indexOf не расскажет нам реальную историю ...

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

  1. indexOf должен возвращать числовое значение, чтобы при обнаружении совпадения вы знали, где оно находится
  2. действительные индексы всегда гарантируются целыми числами
  3. индексы массива (и строки) в Java начинаются с нуля
  4. Java строго типизирован
  5. целочисленные числовые типы подписаны в Java

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

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

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...