2017-02-02 6 views
1

Javaメソッドのイントロスペクション、特に例外に関する質問があります。私は、次のコードを持って言う:Java例外をスローイントロスペクション

private String getCustomReportResponse(HttpsURLConnection customReportConnection) { 
    int responseCode = 0; 

    try { 
     responseCode = customReportConnection.getResponseCode(); 
     return httpResponseBodyExtractor.extractResponseBodyFrom(customReportConnection); 
    } catch (IOException e) { 
     translateIntoRelevantException(responseCode, e); 
    } 
} 

のは、tryブロックで両方のステートメントを言ってみましょうIOExceptionが投げすることができる - その場合には、translateIntoRelevantExceptionメソッドが呼び出され、次のようになりた:

private void translateIntoRelevantException(int responseCode, IOException e) { 
    if(is5xxResponseCode(responseCode)) { 
     throw new ServerResponseException("Could not generate report - returned response code " + responseCode, e); 
    } 

    throw new ReportException("GeminiReportException: Unable to parse response from HTTP body when requesting custom Gemini report.", e); 
} 

何が起きても、Stringが返されるか、例外がスローされます。 getCustomReportResponseを除いて、メソッドはcatchブロックの後にreturnステートメントを追加せずにコンパイルされません。これは絶対に到達できません。実際、もし私がtranslateIntoRelevantExceptionの内容をキャッチブロックの中に入れたら、それはコンパイルされます。

例外をスローする例外は実行時例外ですが、私は例外をチェックするようにも試みましたが、問題は残っています。

誰かが理由を説明できますか?

答えて

1

これは、 "rethrow"ヘルパーメソッドに直面するcommon problemです。

translateIntoRelevantExceptionというメソッドが返されないことをコンパイラは認識していません(また、表示する方法もありません)。

したがって、tryブロックの後に続くコードパスがあると考えます。ですから、return null(またはthrow new RuntimeException("should never come here")「デッドコード」に配置する必要があります。

あなたはtryブロックの後にそれを置く必要はありません、あなたはcatchの内側にそれを置くことができます。

try { 
    responseCode = customReportConnection.getResponseCode(); 
    return httpResponseBodyExtractor.extractResponseBodyFrom(customReportConnection); 
} catch (IOException e) { 
    translateIntoRelevantException(responseCode, e); 
    throw new RuntimeException("should never come here"); 
} 

がそれですおそらくきれいの実装に依存すべきではありません。そして、あなたは

throw translateIntoRelevantException(responseCode, e); 
+0

感謝。したがって、メソッドの内容(translateIntoRelevantException)をcatchブロックに移動すると(コンテンツは暗黙的に無効になり、100%のケースで例外がスローされます)、動作します。私は、コンパイラがメソッドを見て、すべてのケースで例外がスローされていることを知ることができると考えました。コンパイラがモジュール化を不利にしているようですが、それは変です。 –

+0

もう一つのクールなトリックです:http:// stackoverflow。com/a/39719455/14955 – Thilo

+1

いいえ、コンパイラーは* into *メソッドを、宣言されたシグネチャだけで探すわけではありません。そして、メソッドが決して返ってこないことを宣言する方法はありません(例えば、スカラでは、戻り値の型が単にそれを行うために 'Nothing'と言うことができます)。メソッドの実装を見ると、同じクラスのプライベートメソッドに対しては機能するかもしれませんが、動的メソッドディスパッチ(サブクラス化)が関わるとすぐに、それはもう動作しません。 2つを区別することは問題の価値がないようです。 – Thilo

1

コンパイルgetCustomReportResponseの操作を行うことができ、それを投げるだけreturn例外の代わりにヘルパーを持っています複数の理由のため:

  • translateIntoRelevantExceptionの実装が使用できない場合があります(それは別のライブラリで、別のクラスにすることができます)。
  • translateIntoRelevantExceptionの変更は、すべての呼び出しメソッドを壊す可能性があります。代替案として

あなたは例外を返し、その後、クライアントコードでそれを投げることができます。

private IOException translateIntoRelevantException(int responseCode, IOException e) { 
    if(is5xxResponseCode(responseCode)) { 
     return new ServerResponseException("Could not generate report - returned response code " + responseCode, e); 
    } 

    return new ReportException("GeminiReportException: Unable to parse response from HTTP body when requesting custom Gemini report.", e); 
} 

そして、このようにそれを呼び出す:答えるため

throw translateIntoRelevantException(responseCode, e); 
+0

@DannyNoam父のコンパイラは 'getString'の実装をチェックする必要はありません。メソッドのシグネチャは、それが正しく呼び出されたことを確認するのに十分です。 –

+1

ありがとうございました! –