Javaメソッド宣言でthrowsを使用するのはいつですか?


82

そのため、Javaでの例外処理について基本的には十分に理解していると思いましたが、最近、混乱と疑問を与えるコードを読んでいました。ここで取り上げたい主な疑問は、次のようなJavaメソッド宣言をいつ使用する必要があるかということです。

    public void method() throws SomeException
    {
         // method body here
    }

私が収集したいくつかの同様の投稿を読んだところ、throwsは、メソッドの実行中にSomeExceptionがスローされる可能性があるという一種の宣言として使用されています。

私の混乱は、次のようなコードから来ています。

     public void method() throws IOException
     {
          try
          {
               BufferedReader br = new BufferedReader(new FileReader("file.txt"));
          }
          catch(IOException e)
          {
               System.out.println(e.getMessage());
          }
     }

この例でスローを使用したい理由はありますか?IOExceptionのような基本的な例外処理を行っているだけの場合は、try / catchブロックが必要になるだけのようです。

回答:


79

例外タイプをキャッチしている場合は、再スローする場合を除いて、スローする必要はありません。あなたが投稿する例では、開発者は両方ではなく、どちらか一方を行うべきでした。

通常、例外を除いて何もするつもりがない場合は、それをキャッチするべきではありません。

あなたができる最も危険なことは、例外をキャッチし、それで何もしないことです。

例外をスローすることが適切な場合についての良い議論はここにあります

いつ例外をスローしますか?


2
チェックされていない例外も「throws」を使用してメソッドシグネチャで宣言する必要がありますか、それともチェックされた例外には「throws」のみを使用するのが慣例ですか?
コーディ

この回答は、質問の中心的な側面であるthrowsキーワードの使用に直接対処するものではありません。
ブレントブラッドバーン

@hvgotcodes例外をキャッチして何もしないとどうなりますか?
manoj 2018

@manoj重要な情報が失われるため、物事が壊れて理解できなくなるリスクがあります。例外をキャッチして何もしないことが問題ない場合がありますが(必ずしもJavaである必要はありません)、それらを文書化する必要があります。たとえば、javascriptでは、ブラウザによっては存在しない可能性のある機能を呼び出そうとすることができます。これは必ずしも注意が必要なエラーではありません。
hvgotcodes 2018

22

メソッドがチェック例外をスローする場合にのみ、メソッドにthrows句を含める必要があります。メソッドが実行時例外をスローする場合、そうする必要はありません。

チェックされた例外とチェックされていない例外の背景については、http//download.oracle.com/javase/tutorial/essential/exceptions/runtime.htmlを参照してください。

メソッドが例外をキャッチして内部で処理する場合(2番目の例のように)、throws句を含める必要はありません。


9

あなたが見たコードは理想的ではありません。次のいずれかを行う必要があります。

  1. 例外をキャッチして処理します。その場合、throwsは不要です。

  2. try/catch;を削除します。この場合、例外は呼び出しメソッドによって処理されます。

  3. 例外をキャッチし、場合によっては何らかのアクションを実行してから、(メッセージだけでなく)例外を再スローします。


2

あなたは正しいです、その例ではそれthrowsは不必要です。以前の実装からそこに残された可能性があります-おそらく、例外は、catchブロックでキャッチされるのではなく、元々スローされていました。


2

投稿したコードが間違っています。IOExceptionを処理するために特定の例外をキャッチしているが、キャッチされていない例外をスローしている場合は、例外をスローする必要があります。

何かのようなもの:

public void method() throws Exception{
   try{
           BufferedReader br = new BufferedReader(new FileReader("file.txt"));
   }catch(IOException e){
           System.out.println(e.getMessage());
   }
}

または

public void method(){
   try{
           BufferedReader br = new BufferedReader(new FileReader("file.txt"));
   }catch(IOException e){
           System.out.println("Catching IOException");
           System.out.println(e.getMessage());
   }catch(Exception e){
           System.out.println("Catching any other Exceptions like NullPontException, FileNotFoundExceptioon, etc.");
           System.out.println(e.getMessage());
   }

}


1

あなたが与えた例では、メソッドは決してIOExceptionをスローしないので、宣言は間違っています(しかし有効です)。私の推測では、元のメソッドはIOExceptionをスローしましたが、その後、内部の例外を処理するように更新されましたが、宣言は変更されていません。


1

これは答えではなくコメントですが、フォーマットされたコードでコメントを書くことができなかったので、ここにコメントがあります。

あるとしましょう

public static void main(String[] args) {
  try {
    // do nothing or throw a RuntimeException
    throw new RuntimeException("test");
  } catch (Exception e) {
    System.out.println(e.getMessage());
    throw e;
  }
}

出力は

test
Exception in thread "main" java.lang.RuntimeException: test
    at MyClass.main(MyClass.java:10)

そのメソッドは「スロー」例外を宣言しませんが、それらをスローします!トリックは、スローされた例外がRuntimeExceptions(チェックされていない)であり、メソッドで宣言する必要がないことです。彼女が見るのは「投げる」だけなので、メソッドの読者にとっては少し誤解を招く恐れがあります。ステートメントがスロー例外の宣言なし

今、私たちが持っている場合

public static void main(String[] args) throws Exception {
  try {
    throw new Exception("test");
  } catch (Exception e) {
    System.out.println(e.getMessage());
    throw e;
  }
}

メソッドで「スロー」例外を宣言する必要があります。そうしないと、コンパイラエラーが発生します。


コンパイラーは、驚くほど洗練された静的分析を実行して、throwsが必要かどうかを判断します。
ブレントブラッドバーン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.