1.はじめに

このチュートリアルでは、Javaの

throw



throws

を見てみましょう。

いつ使用するかを説明します。

次に、基本的な使い方の例をいくつか示します。

2.

Throw



Throws

簡単な紹介から始めましょう。これらのキーワードは例外処理に関連しています。私たちのアプリケーションのフローの法線が乱されると例外が発生します。

多くの理由があるかもしれません。ユーザーが誤った入力データを送信する可能性があります。

接続が切れたり、その他の予期しない状況が発生する可能性があります。良い例外処理は、これらの不快な瞬間が現れた後もアプリケーションを機能させ続けるための鍵です。

  • コードから例外を明示的にスローするために

    throw

    キーワードを使用しています。

任意のメソッドまたは静的ブロックです。この例外は

Throwableのサブクラスでなければなりません。単一の

throw__で複数の例外をスローすることはできません。


Throws

キーワードをメソッド宣言に含めることができます。

このメソッドからスローされる可能性のある例外を示します

これらの例外はtry-catchで処理する必要があります。

  • これら二つのキーワードは交換可能ではありません!**

3. Javaで

Throw

メソッドから例外をスローするという基本的な例を見てみましょう。

まず、簡単な計算機を書いていると想像してください。基本的な算術演算の1つは除算です。そのため、この機能を実装するように依頼されました。

public double divide(double a, double b) {
    return a/b;
}

ゼロで割ることはできないので、既存のコードに変更を加える必要があります。例外が発生するのは良い瞬間だと思われます。

これをやろう:

public double divide(double a, double b) {
    if (b == 0) {
        throw new ArithmeticException("Divider cannot be equal to zero!");
    }
    return a/b;
}

ご覧のとおり、

ArithmeticException

を使用したことが私たちのニーズに完全に合っています。例外メッセージである単一の

String

コンストラクタパラメータを渡すことができます。

3.1. 良い習慣

  • 私たちは常に最も具体的な例外を好むべきです** 私たちは私たちの例外的なイベントに最適なクラスを見つける必要があります。たとえば、

    __ IllegalArgumentExceptionの代わりに


    NumberFormatExceptionをスローします。


    不特定の

    Exception__を投げるのは避けるべきです。

たとえば、

java.lang

パッケージには

Integer

クラスがあります。ファクトリメソッド宣言の1つを見てみましょう。

public static Integer valueOf(String s) throws NumberFormatException

これは

__Stringから

Integer

インスタンスを作成する静的ファクトリメソッドです。


誤った入力

String

の場合、メソッドは

NumberFormatExceptionをスローします。

  • 私たち自身の、より説明的な例外を定義することをお勧めします。 __

実装例を見てみましょう。

public class DivideByZeroException extends RuntimeException {

    public DivideByZeroException(String message) {
        super(message);
    }
}

3.2. 既存の例外をラップする

時々私達は私達によって定義された例外に既存の例外をラップしたいです。

私たち自身の例外を定義することから始めましょう:

public class DataAcessException extends RuntimeException {

    public DataAcessException(String message, Throwable cause) {
        super(message, cause);
    }
}

コンストラクタは、例外メッセージと原因の2つのパラメータを取ります。これらは

Throwableの任意のサブクラスです。


__findAll()

__functionの偽の実装を書きましょう。

public List<String> findAll() throws SQLException {
    throw new SQLException();
}

それでは、

SimpleService

でリポジトリ関数を呼び出してみましょう。その結果、__SQLExceptionが発生する可能性があります。

public void wrappingException() {
    try {
        personRepository.findAll();
    } catch (SQLException e) {
        throw new DataAccessException("SQL Exception", e);
    }
}


SQLException



__DataAccessExceptionという独自の例外にラップし直しています。

__すべて以下のテストで検証されています。

@Test
void whenSQLExceptionIsThrown__thenShouldBeRethrownWithWrappedException() {
    assertThrows(DataAccessException.class,
      () -> simpleService.wrappingException());
}

これには2つの理由があります。まず最初に、例外ラッピングを使用します。これは、コードの残りの部分で、システム内で起こり得るすべての例外について知る必要がないからです。

また、上位レベルのコンポーネントは、最下位レベルのコンポーネントについても、それらがスローする例外についても知る必要がありません。

3.3. Javaとのマルチキャッチ

時々、私たちが使用するメソッドはさまざまな例外の多くを投げます。

もっと広範囲のtry-catchブロックを見てみましょう。

try {
    tryCatch.execute();
} catch (ConnectionException | SocketException ex) {
    System.out.println("IOException");
} catch (Exception ex) {
    System.out.println("General exception");
}


execute

メソッドは、

SocketException、ConnectionException、Exception.の3つの例外をスローすることがあります。 2番目のcatchブロックは、


Exceptionまたは他の


Exceptionのサブクラスをキャッチします。

__覚えておいてください、私たちは常により詳細な例外を最初に捉えるべきです。

catchブロックの順番を入れ替えることができます。それで、

SocketException



ConnectionException

をキャッチすることは決してありませんでした。

4. Javaでの

Throws

メソッド宣言に

__throws

__を追加します。

前のメソッド宣言の1つを見てみましょう。

public static void execute() throws SocketException, ConnectionException, Exception

  • メソッドは複数の例外を投げることがあります** メソッド宣言の終わりにコンマで区切られます。チェック済みと未チェックの両方の例外を

    __throwに入れることができます。

    __これらの違いについて以下に説明しました。

4.1. チェック済みおよび未チェックの例外

  • チェック例外は、コンパイル時にチェックされることを意味します。** この例外を処理する必要があることに注意してください。それ以外の場合、メソッドは

    throws

    キーワードを使用して例外を指定する必要があります。

最も一般的なチェック済み例外は、


_ IOException、FileNotFoundException、ParseExceptionです。 FileNotFoundException


FileInputStream


from

Fileを作成するときにスローされる可能性があります。 _

簡単な例があります。

File file = new File("not__existing__file.txt");
try {
    FileInputStream stream = new FileInputStream(file);
} catch (FileNotFoundException e) {
    e.printStackTrace();
}

メソッド宣言に

__throws

__を追加することで、try-catchブロックの使用を避けることができます。

private static void uncheckedException() throws FileNotFoundException {
    File file = new File("not__existing__file.txt");
    FileInputStream stream = new FileInputStream(file);
}

残念ながら、より高いレベルの関数はまだこの例外を処理しなければなりません。それ以外の場合は、__throwsキーワードを使用して、この例外をメソッド宣言に含める必要があります。

反対に、

未チェックの例外はコンパイル時にチェックされません。

最も一般的な未チェックの例外は、

ArrayIndexOutOfBoundsException、IllegalArgumentException、NullPointerExceptionです。

次のコードは__NullPointerExceptionをスローします。おそらくJavaで最も一般的な例外の1つです。

null参照でメソッドを呼び出すと、この例外が発生します。

public void runtimeNullPointerException() {
    String a = null;
    a.length();
}

テストでこの動作を確認しましょう。

@Test
void whenCalled__thenNullPointerExceptionIsThrown() {
    assertThrows(NullPointerException.class,
      () -> simpleService.runtimeNullPointerException());
}

このコードとテストは意味がありません。実行時の例外について説明するのは学習目的のためだけです。

Javaでは、

Error

および

RuntimeException

のすべてのサブクラスは未チェックの例外です。チェック例外は、

__ Throwable

__classの下にある他のすべてのものです。

5.まとめ

この記事では、

throw



__throwsという2つのJavaキーワードの違いについて説明しました。


基本的な使い方を見て、グッドプラクティスについて少し話しました




__チェックされた例外とチェックされていない例外について話しました。

いつものように、ソースコードはhttps://github.com/eugenp/tutorials/tree/master/core-java-lang[私たちのGitHub]で見つけることができます。

Javaでの例外処理についてもっと深く知りたい場合は、https://www.baeldung.com/java-exceptions[Java例外について]の記事をご覧ください。