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
aを実行するだけで、フラグの管理でコードを混乱させる必要がなくなります。その点でコードがきれいになるだけでなく、この省略により実行速度が向上する可能性があります。FlyingPig
boolean isFound
要約すると、次の 2 つのいずれかを選択します。
- 従来の制御フロー アプローチ
- を使用し
boolean isFound
、継続的にチェック - 99.99% の確率で、小切手は「無駄」です。
false
- 最終的に になると
true
、再帰を停止し、最初の呼び出しに適切に巻き戻すことができることを確認する必要があります。
- を使用し
FlyingPig
アプローチ- 気にしないでください
boolean isFound
。 - 見つかった場合は、ただ
throw new FlyingPig()
; それは期待されているので、それには がありますcatch
。 - フラグの管理、
boolean
続行する必要がある場合の無駄なチェック、再帰を手動で巻き戻す簿記などはありません。
- 気にしないでください
質問:
- (ab)例外を使用するこの手法は有効ですか? (名前はありますか?)
- 有効な場合、必要ですか
FlyingPig extends Throwable
、それともException
問題ありませんか? (その状況に例外は何もないのに?)