😸

Java言語における例外処理の投げ方(throw/throwsの違い)

2022/10/09に公開

例外処理の基本
throw/throwsの違い

前提:throw/throwsの違いの復習(意味の違い)

  • throw:例外を報告し、例外処理を実行させる処理(「例外起こるかもね」って言うてるだけ)
public static int div(int a, int b) {
  void testA (int num) {
    if(num == 0) {
        throw new IllegalArgumentException(“引数の値が不正です”);//例外投げる。
        //「例外が発生するかもですよ〜」って報告しとるだけ。
    }
    //IllegalArgumentException=非チェック例外
  }
}
  • throws:自分のメソッド内で処理を行わせるのではなく(try/catch)、呼ばれる側に例外を投げる処理
    実際は例外を「かわして」いる(呼び出し先のメソッドに例外の処理をさせるから)
    (「例外起きるかもだから、呼び出したらそっちで責任取れよ?」って感じ)
void testB () throws FileNotFoundException {//例外投げる。だが処理を「かわす」
  //throws:「①例外起きるかもだから、飛び出したらそっちで責任取れよ?」(かわした)
    FileReader r = new FileReader(“sample.txt”);//ファイルが読み込めない時もある。
    System.out.print(“ファイルを読み込みました”); 
}
void testC () {
    try {
        testB(); 
        //②呼び出すので例外起きたら以下を実行するようにしておこう。(「責任取ります」)
    } catch (FileNotFoundException e) { 
        System.out.print(“ファイルが存在しませんでした”);   
    }
    //FileNotFoundException=チェック例外
}

本題:「例外の投げ方」について

  • 実はチェック例外・非チェック例外のような「例外の種類」ごとに「throwsをつけるorつけない」は変わってくる。

    • 非チェック例外を投げる時:throw [例外名] でOK
    • チェック例外を投げる時メソッド宣言の後に[throws] をつけ例外型を宣言する。
      そのメソッドの中で thorw new [例外名] として投げる

要するに

チェック例外を投げる場合はメソッド宣言の後に[throws] をつけろ」ってこと

非チェック例外を投げる(処理任意)

  • throw [非チェック例外] と投げる時は、普通にthrowで例外を投げればいい
public static int div(
  int a, int b) {
  if(b == 0){
    throw new ArithmeticException(); 
    //非チェック例外(ArithmeticException)でかつ、例外宣言してるだけ
  }
  return a / b
}

チェック例外を投げる(処理必須)

  • チェック例外を throw [チェック例外名] として投げる時はそのメソッド名の後に メソッド名 throws としてthrowsをつける
public static void main(String[] args){
  try{
    sub();//呼び出し先
  } catch (Exception e) {
    System.out.println("例外が発生");
  }
}
public stataic void sub() throws Exception{//呼び出し元
  //①チェック例外を投げる時は メソッド名 throws Exception1 Exception2... って感じで宣言する
  throw new Exception();
  //チェック例外(Exception)を投げる。かつ、処理をかわしてmain関数に例外処理を流してる。
}

チェック例外を投げる場合は上記例①のようにメソッドにthrows宣言を追加して、どんな種類の例外を投げるのかを宣言しなければなりません。このthrows宣言は省略できません。宣言しないとコンパイルエラーになります。

結論:「throw/throwsの違い」の分類方法は二つある

  • 前提部分で述べた、「宣言する・かわす」のような「意味」の違い
  • 本題部分で述べた、「非チェック例外・チェック例外」のような「投げる例外の種類」の違い

がある。

結論の考察

  • throwsは「例外処理を呼び出し先のメソッドに委託する&チェック例外(処理必須)を投げる時に必ずつけないといけない」と言うことなので「チェック例外」は必ず(処理必須だから、)

呼び出し元のメソッドにthrowsをつけ、呼び出し先のメソッドで必ずtry/catchで例外処理をする」

これがマストになる。上記の チェック例外を投げる(処理必須) の例でも同じである。

復習:例外の種類と例外型について

例外型の基本

  • チェック例外:処理必須。コンパイラが実行前に気づくので、必ず例外処理が要る。なければ「コンパイルエラー」になる

    チェック例外の例外型

    • Exceptionクラスが親クラス。子クラスには
      • IOException
        • FileNotFoundException
      • SQLException
      • ReflectionOperationException

    などがある


  • 非チェック例外:処理任意。「プログラムの実行中」に起こるエラーなので「実行時例外」とも言われる

    非チェック例外の例外型

    • RuntimeExceptionクラスが親クラス。子クラスには
      • ArithmeticException(算術エラー・0で割ったなど)
      • NullPointerException(アクセスした参照がNull)
      • IndexOutOfBoundsException(インデックスが範囲外)
      • IllegalArgumentException(引数に不正値を持たせている)

    などがある


  • システムエラー:修復不可能なエラー。処理はいらん

最後に

最初参考記事で調べた違いと「オブジェクト指向徹底解説」で調べた「throw・throwsの違い」の説明が違いすぎて困惑した。

「結局throw・throwsの違いはなんなのや」

と。

参考記事では

  • throwは、例外を意図的に発生させて、例外処理を実行させることができます。
  • throwsは、メソッド内で例外が発生した場合、自身のメソッド内でcatchするのではなく呼び出し元に例外を投げます。

って言うてたのに書籍の方では
「投げる例外が、非チェック例外orチェック例外の違い」って言うててなんじゃこりゃってなったので二つの分類方法を併せてまとめてみた

GitHubで編集を提案

Discussion