\r\n\r\n
初心者のプログラマーにとって、例外処理の概念は理解するのが難しいかもしれません。概念そのものが難しいわけではないのですが、専門用語があるために実際よりも高度に感じられることがあります。そして、あまりにも強力なため、簡単に悪用されてしまうのです。
この記事では、例外とは何か、なぜ例外が重要なのか、どのように使うのか、そして避けるべきよくある間違いについて学びます。最近のほとんどの言語は何らかの例外処理を備えているので、Javaから始めれば、これらのヒントのほとんどを持ち運ぶことができます。
Javaでは、アプリケーションの実行中に例外(または "exception")を投げるオブジェクトを "exception "と呼びます。このような例外を投げることは、基本的に例外オブジェクトを生成することを意味する(エラーを「発生」させるのと同じような意味)。
この利点は、スローされた例外をキャッチすることで、例外の状況を処理し、何事もなかったかのようにアプリケーションの実行を継続させることができることです。例えば、C言語ではNULLポインタはアプリケーションをクラッシュさせる可能性がありますが、Javaでは、NULLポインタのスローとキャッチが可能です。
NullPointerExceptionは、空の変数がクラッシュを引き起こす可能性がある前に
例外は単なるオブジェクトですが、1つ重要な特徴があることを覚えておいてください。
Exceptionクラスまたはそのサブクラス
Exception.Javaには様々な例外が組み込まれていますが、必要であれば自分で作ることもできます。Javaの代表的な例外には、以下のようなものがあります。
では、例外が発生した場合はどうなるのでしょうか。
まず、JavaはIMMEDIATEメソッドの中に、投げられた例外の種類を処理するコードがあるかどうかを調べます。ハンドラが存在しない場合、現在のメソッドを呼び出すメソッドを調べ、そこにハンドルが存在するかどうかを確認します。そうでない場合は、それを呼び出したメソッドを調べ、次にそのメソッドを調べる、という具合になります。例外が捕捉されない場合、アプリケーションはスタックトレースを表示し、クラッシュします。(実は、これは単純なクラッシュよりも微妙なのですが、この記事の範囲外の高度なトピックです)。
スタックトレースは、Javaが例外ハンドラを探すときに通過するすべてのメソッドのリストです。
Exception in thread "main" java.lang.NullPointerException at com.example.myproject.Book.getTitle(Book.java:16) at com.example.myproject.Author.getBookTitles(Author.java:25) at com.example.myproject.Bootstrap.main(Bootstrap.java:14)ここから学べることはたくさんあります。まず、投げられた例外は
NullPointerExceptionになる。
getTitle()16行目のメソッド book.java このメソッドは
getBookTitles()25行目 author.java このメソッドは
main()14行目 boot.java このように、すべて把握しておくと、デバッグが楽になります。
しかし、例外の本当の利点は、例外をキャッチしてエラーを修正し、クラッシュすることなくアプリケーションを回復することで「処理」できることです。
があると仮定して
someMethod()整数を受け取り、その整数が0より小さいか100より大きい場合に壊れる可能性のあるロジックを実行します。これは、例外を投げるのに良い場所かもしれません。
public void someMethod(int value) { if (value < 0 || value > 100) { throw new IllegalArgumentExceptionこの例外をキャッチするために
someMethod()try-catchブロックを呼び出して使用する。
public void callingMethod() { try { someMethod(200); someOtherMethod(); } catch (IllegalArgumentException e) { // handle the exception in here } // ...}tryブロックの中のものは、例外が発生するまで順次実行されます。例外が発生すると、それ以降の文はすべてスキップされ、アプリケーションロジックは直ちにキャッチブロックにジャンプします。
この例では、tryブロックに入った後、すぐに
someMethod().200は0と100の間にないため
IllegalArgumentExceptionの実行を直ちに終了させます。
someMethod()であり,try ブロックの残りのロジックはスキップされます (
someOtherMethod()が呼び出されることはない)、キャッチブロック内で実行が再開される。
を呼び出すとどうなるか?
someMethod(50)それどころか、この
IllegalArgumentException投げることはないでしょう。
someMethod()tryブロックは通常通り実行され、その後に
someOtherMethod()someMethod()が終了するのはいつですか?
someOtherMethod()キャッチブロックが終了するとスキップされる
callingMethod()続けていきます。
各 try ブロックは、複数の catch ブロックを持つことができることに注意してください。
public void callingMethod() { try { someMethod(200); someOtherMethod(); } catch (IllegalArgumentException e) { // handle the exception in here } catch (NullPointerException e) { // handle the exception in here } // ...}また、オプションでfinallyブロックがあることに注意してください。
public void method() { try { // ... } catch (Exception e) { // ... } finally { // ... }}finallyブロック内のコードは、何が起こっても常に実行されます。tryブロックの中にreturn文がある場合、finallyブロックはreturnメソッドの前に実行されます。catchブロックの中で別の例外が投げられた場合、finallyブロックは例外が投げられる前に実行されます。
最終ブロックは、メソッドの終了前にクリーンアップする必要があるオブジェクトがある場合に使用します。例えば、try ブロックでファイルを開いてから例外を投げる場合、finally ブロックでは、メソッドを抜ける前にファイルを閉じることができます。
catchブロックの代わりにfinallyブロックを使うことができることに注意してください。
public void method() { try { // ... } finally { // ... }}これにより、スローされた例外をメソッドコールスタック上に伝搬させながら、必要なクリーンアップを行うことができます (つまり、ここで例外を処理したくないけれども、最初にクリーンアップする必要がある)。
多くの言語と異なり、Javaはチェックされた例外とチェックされていない例外を区別しています(例えば、C#はチェックされていない例外のみです)。チェックした例外は、それを投げるメソッドでキャッチする必要があり、そうでなければコードはコンパイルされません。
選択された例外を作成するには、まず
Exceptionチェックされていない例外を作成するには、まず
RuntimeException.
チェックされた例外を投げるメソッドは、メソッドのシグネチャで例外を示すthrowsキーワードを使用する必要があり、Javaには組み込みの
IOExceptionがチェックされた例外である場合、次のコードはコンパイルされません。
public void wontCompile() { // ... if (someCondition) { throw new IOException(); } // ...}まず、選択した例外を発生させることを宣言する必要があります。
public void willCompile() throws IOException { // ... if (someCondition) { throw new IOException(); } // ...}例外を発生させると宣言しても、実際には例外を発生させないメソッドもあり、その場合でも例外をキャッチしないとコンパイルできないことに注意してください。
チェック付き例外とチェックなし例外はいつ使うべきですか?
Javaの公式ドキュメントに、この件に関するページがあります。その違いは、「クライアントが例外から回復することが合理的に期待できる場合は、チェック済みの例外に設定する」という簡潔な経験則でまとめられている。クライアントが例外から回復するためのアクションを実行できない場合、チェックされていない例外に設定します。"
しかし、このガイドラインは時代遅れかもしれません。一方、チェックされた例外は、より堅牢なコードを生成します。一方、Javaほど例外をチェックする言語は他にありません。これは2つのことを示唆しています。1つは、この機能は他の言語が盗むほど有用ではないこと、もう1つは、例外を完全に排除してもよいということです。また、チェックされた例外は、Java 8で導入されたラムダ式をうまく扱えません。
例外は便利ですが、簡単に悪用されたり誤用されたりします。ここでは、例外で混乱しないようにするためのヒントとベストプラクティスを紹介します。
これで、例外とは何か、なぜ使われるのか、自分のコードにどのように組み込めばいいのかを理解するのに十分な知識を得たはずです。コンセプトを完全に理解できなくても、大丈夫です!頭の中で「カチッ」と音が鳴るまで時間がかかったので、焦らなくても大丈夫です。ゆっくりでいいんです。
ご質問や、私が見逃している例外に関するヒントがあれば、下のコメント欄で教えてください。