第10章. 機能的例外処理
この作品はAIを使って翻訳されている。ご意見、ご感想をお待ちしている:translation-feedback@oreilly.com
完璧でエラーのないコードを書きたいのは山々だが、それはほとんど不可能な努力だ。 だからこそ、コード中の不可避な問題に対処する方法が必要なのである。 このような制御フローの混乱や異常事態に対処するためにJavaが選択したメカニズムが、例外である。
例外処理は、たとえ命令型コードやOOコードであっても厄介なものである。 しかし、例外処理を関数型アプローチと組み合わせることは、テクニックに考慮すべき点や要求事項が多いため、本当に難しいことである。 これを支援するサードパーティライブラリはあるが、長期的にはそれだけに頼りたくないかもしれないし、全体的により関数的なアプローチに適応する代わりに、新たな依存関係によって技術的負債を負うことになるかもしれない。
この章では、ラムダを使った関数型プログラミングにおける、さまざまな種類の例外とその影響について説明する。 ラムダで例外を処理する方法と、関数型コンテキストにおける制御フローの混乱にアプローチする別の方法についても学ぶ。
Javaの例外処理を簡単に理解する
一般化すると、例外とはプログラムの実行中に発生し、通常の命令の流れを中断させる特殊な事象のことである。 この概念はJavaだけでなく、さまざまなプログラミング言語に存在し、その起源はLispにまでさかのぼる。1
実際の例外処理方法は言語に依存する。
try-catchブロック
Javaが選択したメカニズムは、try-catch ブロックであり、これは言語に不可欠な要素である:
try{returndoCalculation(input);}catch(ArithmeticExceptione){this.log.error("Calculation failed",e);returnnull;}
catch (ブロック)が複数必要な代わりに、| (パイプ)をブロックの間に使うことで、multi-catch (ブロック)で複数のExceptionをキャッチすることができる:
try{returndoCalculation(input);}catch(ArithmeticException|IllegalArgumentExceptione){this.log.error("Calculation failed",e);returnnull;}
リソースを処理する必要がある場合、try-with-resources を使用すると、AutoCloseable を実装しているリソースは自動的にクローズされる:
try(varfileReader=newFileReader(file);varbufferedReader=newBufferedReader(fileReader)){varfirstLine=bufferedReader.readLine();System.out.println(firstLine);}catch(IOExceptione){System.err.println("Couldn't read first line of "+file);}
どの型を使うにせよ、例外がスローされた起点からコールスタックの一番近いcatch まで呼び出すか、利用可能なものがない場合は現在のスレッドをクラッシュさせることで、コードの実行の流れを混乱させることになる。 ...