\r\n\r\n

javaの例外を正しく処理する方法

この記事では、Javaの例外とは何か、なぜ例外が重要なのか、どのように使うのか、そして避けるべきよくある間違いについて学びます...

初心者のプログラマーにとって、例外処理の概念は理解するのが難しいかもしれません。概念そのものが難しいわけではないのですが、専門用語があるために実際よりも高度に感じられることがあります。そして、あまりにも強力なため、簡単に悪用されてしまうのです。

この記事では、例外とは何か、なぜ例外が重要なのか、どのように使うのか、そして避けるべきよくある間違いについて学びます。最近のほとんどの言語は何らかの例外処理を備えているので、Javaから始めれば、これらのヒントのほとんどを持ち運ぶことができます。

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 このように、すべて把握しておくと、デバッグが楽になります。

しかし、例外の本当の利点は、例外をキャッチしてエラーを修正し、クラッシュすることなくアプリケーションを回復することで「処理」できることです。

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のチェックされた例外とチェックされていない例外

多くの言語と異なり、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で導入されたラムダ式をうまく扱えません。

javaの例外を利用するためのガイド

例外は便利ですが、簡単に悪用されたり誤用されたりします。ここでは、例外で混乱しないようにするためのヒントとベストプラクティスを紹介します。

  • 一般的な例外より、特定の例外を優先する。可能な場合は IllegalArgumentException よりも NumberFormatException を使用し、不可能な場合は RuntimeException よりも IllegalArgumentException を使用する。
  • スローアブルキャッチしない!?Exceptionクラスは実際にはThrowableを継承しており、キャッチブロックは実際にはThrowableやThrowableを継承するクラスで動作します。しかし、ErrorクラスはThrowableも継承しており、Errorは回復不可能な深刻な問題を示すので、決してキャッチしたくはない。
  • エクセプショ ンは絶対に捕まらない!InterruptedException は Exception を継承しているので、Exception を捕捉するブロックは InterruptedException も捕捉することになり、これは非常に重要な例外で、何をやっているか分からない限り(特にマルチスレッドのアプリケーションでは)いじりたくないものです。どの例外をキャッチすればいいのかわからない場合は、何もキャッチしないことをお勧めします。
  • デバッグを容易にするために、説明的なメッセージを使用します。例外を投げる場合、引数としてStringmessageを与えることができる。このメッセージは、Exception.getMessage()メソッドを使ってキャッチブロック内でアクセスできますが、例外がキャッチされなかった場合、このメッセージもスタックトレースの一部として表示されます。
  • excepti***を捕まえたり無視したりしないようにする。チェックされたexcepti***の不便さを回避するために、多くの初心者や怠惰なプログラマはcatchブロックを設定しますが、それは空のままです。悪い!例外は常に優雅に処理しますが、それができない場合は、最低でもスタックトレースを出力して、例外が発生したことを確認できるようにしてください。Exception.printStackTrace()メソッドを使用して行うことができます。
  • 使いすぎの異常に注意する。ハンマーがあれば、すべてが釘に見える。例外について初めて学ぶと、すべてを例外にしなければならないと感じるかもしれません。アプリケーションの制御フローの多くは、例外処理に集約される。例外は「異常」な出来事であることを忘れてはならない

これで、例外とは何か、なぜ使われるのか、自分のコードにどのように組み込めばいいのかを理解するのに十分な知識を得たはずです。コンセプトを完全に理解できなくても、大丈夫です!頭の中で「カチッ」と音が鳴るまで時間がかかったので、焦らなくても大丈夫です。ゆっくりでいいんです。

ご質問や、私が見逃している例外に関するヒントがあれば、下のコメント欄で教えてください。

あなたが興味を持っているかもしれない記事

匿名者
匿名者

0 件の投稿

作家リスト

  1. admin 0 投稿
  2. 匿名者 0 投稿

おすすめ