例外は、呼び出し元のメソッドが処理する場合でも、すぐに呼び出すコードが処理する準備ができていない可能性が高い条件を表す必要があります。たとえば、ファイルから一部のデータを読み取り、有効なファイルが有効なレコードで終了し、部分的なレコードから情報を抽出する必要がないと合法的に仮定するコードを考えてみましょう。
データ読み取りルーチンが例外を使用せず、読み取りが成功したかどうかを単に報告した場合、呼び出しコードは次のようになります。
temp = dataSource.readInteger();
if (temp == null) return null;
field1 = (int)temp;
temp = dataSource.readInteger();
if (temp == null) return null;
field2 = (int)temp;
temp = dataSource.readString();
if (temp == null) return null;
field3 = temp;
など。有用な作業ごとに3行のコードを費やす。対照的に、もしreadInteger
ファイルの終わりに遭遇すると例外がスローされ、呼び出し元が単に例外を渡すことができる場合、コードは次のようになります。
field1 = dataSource.readInteger();
field2 = dataSource.readInteger();
field3 = dataSource.readString();
物事が正常に機能する場合にはるかに重点を置いて、よりシンプルでクリーンな外観。すぐに呼び出し元が条件を処理することを期待している場合、エラーコードを返すメソッドは、例外をスローするメソッドよりも役立つことが多いことに注意してください。たとえば、ファイル内のすべての整数を合計するには:
do
{
temp = dataSource.tryReadInteger();
if (temp == null) break;
total += (int)temp;
} while(true);
対
try
{
do
{
total += (int)dataSource.readInteger();
}
while(true);
}
catch endOfDataSourceException ex
{ // Don't do anything, since this is an expected condition (eventually)
}
整数を要求するコードは、これらの呼び出しの1つが失敗することを予期しています。コードに無限ループを使用させ、それが発生するまで実行することは、戻り値を介して失敗を示すメソッドを使用するよりもはるかにエレガントではありません。
多くの場合、クラスはクライアントがどの条件を予期するか、または予期しないかを知らないため、一部の呼び出し元が予期し、他の呼び出し元が予期しない方法で失敗する可能性のある2つのバージョンのメソッドを提供すると便利です。そうすることで、そのようなメソッドを両方のタイプの呼び出し元できれいに使用できるようになります。また、呼び出し側が予期しない状況が発生した場合、「try」メソッドでさえ例外をスローすることに注意してください。たとえばtryReadInteger
、クリーンなファイルの終わり状態に遭遇した場合、例外をスローすべきではありません(呼び出し側がそれを予期していなかった場合、呼び出し側はreadInteger
)。一方、たとえば、データを含むメモリスティックが取り外されたためにデータを読み取れなかった場合は、おそらく例外をスローする必要があります。このようなイベントは常に可能性として認識される必要がありますが、即時の呼び出しコードが応答に役立つ何かを実行する準備ができることはほとんどありません。ファイルの終わりの状態と同じ方法で報告されるべきではありません。