Java позволяет вам создать совершенно новый подтип Throwable
, например:
public class FlyingPig extends Throwable { ... }
Теперь, очень редко , я могу сделать что-то вроде этого:
throw new FlyingPig("Oink!");
и, конечно, в других местах:
try { ... } catch (FlyingPig porky) { ... }
Мои вопросы:
- Это плохая идея? И если так, то почему?
- Что можно было бы сделать, чтобы предотвратить этот подтип, если это плохая идея?
- Поскольку это невозможно предотвратить (насколько я знаю), к каким катастрофам это может привести?
- Если это не такая плохая идея, почему бы и нет?
- Как вы можете сделать что-то полезное из того, что вы можете
extends Throwable
?
Предлагаемый сценарий # 1
Сценарий, в котором я действительно испытывал искушение сделать что-то подобное, имеет следующие свойства:
- «Событие» - это то, что произойдет в конечном итоге . Ожидается . Совершенно определенно это не
Error
, и в этом нет ничего Exception
-al, когда это происходит.
- Поскольку ожидается , будет ожидаться
catch
. Это не будет "скользить" мимо чего-либо. Он не «уйдет» от попыток catch
general Exception
и / или Error
.
- «Событие» происходит крайне редко .
- Когда это происходит, обычно есть глубокий след стека.
Так что, возможно, теперь ясно, что я пытаюсь сказать: FlyingPig
- это результат исчерпывающего рекурсивного поиска.
Объект, который нужно найти, существует: вопрос только в том, чтобы найти его в большом море, которое является пространством поиска. Процесс поиска будет долгим, поэтому относительно дорогая стоимость обработки исключений незначительна. Фактически, традиционная альтернатива конструкции потока управления с использованием флага boolean isFound
может быть более дорогой, потому что она должна проверяться непрерывно в течение всего процесса поиска, скорее всего на каждом уровне рекурсии. Эта проверка завершится неудачно в 99,99% случаев, но абсолютно необходимо распространить условие завершения. В некотором смысле, в то время как действует , проверка неэффективна !
Просто throw
-ing FlyingPig
, когда искомый объект найден, вам не нужно загромождать код с помощью управления boolean isFound
флагом. Это не только очиститель кода, но из-за этого упущения он может работать быстрее.
Итак, подведем итог: выбор между этими двумя:
- Традиционный подход управления потоком
- Использовать
boolean isFound
, проверяется постоянно
- 99,99% времени, чек - это «пустая трата», потому что он все равно будет
false
- Когда оно в конечном итоге становится
true
, вы прекращаете повторение и вам необходимо убедиться, что вы можете правильно отменить первоначальный вызов.
FlyingPig
подход
- Не беспокойтесь о
boolean isFound
.
- Если найдено, просто
throw new FlyingPig()
; ожидается , поэтому для него будет catch
.
- Нет управления флагом
boolean
, нет потраченной впустую проверки, если вам нужно продолжать, нет бухгалтерии, чтобы вручную раскрутить рекурсию и т. Д.
Вопросы:
- Является ли эта техника (ab) с использованием исключения допустимой? (Есть имя для этого?)
- Если допустимо, должно ли
FlyingPig extends Throwable
или Exception
нормально? (хотя в его обстоятельствах нет ничего исключительного?)