プログラミング フォーラムで宗教戦争を始める簡単な方法は、「エラーを処理する最善の方法は何か?」ということです。:)しかし、それは完全に有効な質問です。
ご存知かもしれませんが、Java には、実行時に検出可能な例外とコンパイル時に検出可能な例外の 2 種類があります。(別のラベルのセットは、実行時は「未チェック」、コンパイル時は「チェック済み」です。) コンパイル時に検出可能な例外は、カスタム データベース例外で行っているように、特別に定義された例外をスローしました。チェックされた例外とチェックされていない例外 (例: null ポインターまたは範囲外のインデックス) の大きな違いは、チェックされた例外が必要であるということです。スローされた場合に処理されるか、「throws」キーワードを使用してメソッドのスコープから委任され、呼び出し元のメソッドに処理を強制します。チェックされていないものは (try/catch ブロックを介して) 処理できますが、必須ではありません。非チェック例外も、Exception の子孫であるクラス RuntimeException から派生した特定の例外のみをスローします。(詳細については、 http://docs.oracle.com/javase/7/docs/api/java/lang/RuntimeException.htmlを参照してください)。try/catch ブロックを使用して実行時例外をキャッチできますが、これらの種類の例外を、特定の実行時例外以外で処理されるように移行することはできません (たとえば、実行時の null ポインター参照は、NullPointerException オブジェクトによってのみ処理できます)。またはそのスーパークラス オブジェクトの 1 つだけ)。
では、なぜ「例外の復習レッスン」なのか? 例外を呼び出し元のメソッドに「上向き」にスローするか、例外が発生したメソッド内でその場で処理するかは、例外を生成するコードに続くコードが例外なく「生き残る」ことができるかどうかという問題に大きく関係しているためです。 try/catch ブロックにあるものは何でも正常に完了しました。後続のコードは、本質的に、ヌル ポインター例外などのチェックされない (実行時) 例外が残る可能性がありますか? よくあることです。または、後続のコードは実行可能ですが、信頼できない状態になっている可能性があります (例: フィールド値が希望どおりに設定されていないなど)。または、更新を行うためのデータベースへの呼び出しに関する try/catch ブロックなどの場合、データベース データの状態が目的の処理に対して正しくない可能性があります。
- 例外をローカルで処理または報告せずに上向きにスローします。本質的に、呼び出し元のメソッドに処理の負担をかけます。
- 例外をローカルで処理し、(おそらく) ログに記録/報告してから、catch () {} ブロック内で「return」を使用してメソッドを終了します。
- 例外をローカルで処理し、(おそらく) ログに記録/報告してから、メソッド内のコードの実行を続行します。
私が言ったように、あなたが何をするかは、あなたが何をする必要があるかによって異なります. 個人的には、例外処理は特定のメソッドごとの問題であり、ローカルで処理されると考えています。スローされた例外は、メソッドが意図したタスクを完了できなかったことを意味します。呼び出し元のメソッドがその失敗を補うことができない限り、または例外を作成するメソッド内で、後続のコードは依然として目的を達成できます。呼び出し元のメソッドにスローするということは、これら 2 つのオプションのいずれかをテーブルから外すことを意味するだけであり、さらに悪いことに、すぐにスローされます。そのため、「return」を使用してメソッドを終了する前、またはメソッドを続行する前に、例外の後にピックアップするオプションを取り除きます。コード内の条件をテストするために、try/catch を使用する必要がある場合があります。つまり、コードが次に何をするかを決定する手段として、いくつかのメソッドの例外スローの性質を使用します。ただし、これは一般的に嫌われています。「よりクリーンな」方法が利用可能な場合。[Java の純粋主義者のような純粋主義者はいません。:) ]
もちろん、例外を上向きにスローしても問題ない場合もあります。しかし、IMO では、呼び出し元のメソッドが、呼び出されたメソッドのロジックによって影響を受けるオブジェクトやデータの状態をあまり気にする必要がない場合です。発生する重要性の低い例外を処理するための、より要約された方法と考えています。私の場合、null の可能性があるオブジェクトを使用する前に、null オブジェクト参照を頻繁にチェックすることを好みます。メソッド内の例外のために戻り可能なオブジェクトに null の値を割り当て、それを catch () {} ブロックで返すことは、呼び出されたメソッドが意図したことを実行できなかったことを呼び出し元のメソッドに知らせるために使用される非常に一般的な手法です。 . 例えば:
public meth1() {
Object o = meth2();
if (o != null) {
... do what you need to ...
} else
{
... deal w/ no valid o object ...
}
...
}
private Object meth2() {
Object retnme = new Object();
...
try {
... give it yer best ...
} catch ( Exception e )
{
logException(e); // a call to some logging method.
... clean up bad karma ...
return null;
}
...
return retnme;
}
とはいえ、あなたのコードに関するあなたの差し迫った質問について: 上記に基づいて、私はあなたの状況を完全には知らないことを覚えておいてください.具体的には、その例外を使用して、何らかの理由で、作成しようとしているデータベースが既に存在することを呼び出し元のメソッドに通知したいと考えています。ただし、これが呼び出し元のメソッドに特に使用されないことがわかっている場合は、実行する必要はありません。この決定の一部は、インターフェイスを実装するクラスを使用して、データベースが存在するかどうかを知る必要があるかどうかにかかっています。ただし、このような戦略の使用を回避する方法は、インターフェイスとクラス ファイルを編集して、メソッドが void ではなくブール値を返すようにすることです。「true」が返された場合、データベースは作成されています。「偽」の場合、なんらかの理由ではありませんでした。int を返すこともでき、その値に応じて、データベースの作成が成功したかどうかを示します。たとえば、値 0 は成功を意味し、値 1..n は失敗の理由を表すことができます。もちろん、1 つの値はデータベースが既に存在するという事実を表します。
本当に、空は限界です。:) これがお役に立てば幸いです。