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