2013-02-22 4 views
16

一般に、Javaコンパイラはメソッドが常に例外をスローする情報を伝播しないため、すべてのコードパスが完了したことを検出しません。メソッドが常に例外をスローすることをコンパイラに伝えることは可能ですか?

(これは、Javaコンパイラが各クラスを独立してコンパイルしているためです)。

このようなことを書いてみると問題になります。

public class ErrorContext { 
    public void fatalISE(String message) { 
     String context = "gather lots of information about the context of the error"; 
     throw new IllegalStateException(context +": " + message); 
    } 
} 

public class A { 
    public MyObject myMethod() { 
     if (allIsGood()) { 
      return new MyObject(); 
     } 
     ErrorContext.fatalISE("all is not good"); 
    } 
} 

(すなわち、コンテキスト情報を収集する「アサーションヘルパー」の一種)。

myMethodが必ずしもMyObjectを返すとは限りませんので、コンパイラは不平を言います。

私の知るところでは、メソッドが常にスローすることを示す特定の注釈はありません。

+1

に別のポストでソリューションを継続ウィルていることを確認し、[ここ](のhttp:/ /stackoverflow.com/a/11249665/1402846)。 – Pang

答えて

30

簡単な回避策は、あなたのfatalISE方法はないをさせることですスロー例外が、唯一それを作成します。

public class ErrorContext { 
    public IllegalStateException fatalISE(String message) { 
     String context = "gather lots of information about the context of the error"; 
     return new IllegalStateException(context +": " + message); 
    } 
} 

public class A { 
    public MyObject myMethod() { 
     if (allIsGood()) { 
      return new MyObject(); 
     } 
     throw ErrorContext.fatalISE("all is not good"); 
    } 
} 

コンパイラが見つからないreturn文句を言うではない知っているだろう、この道を。 throwの使用を忘れると、コンパイラが通常不平を言ってしまうからです。

+6

これは、コードを読むときの明快さの利点を持っています。 –

+0

読みやすく、シンプルで安全です。すばらしいです ! – Zorglub

7

私が使用してトリックはその後、MyMethodはで、使用

public <T> T fatalISE(String message) { 
    String context = "gather lots of information about the context of the error"; 
    throw new IllegalStateException(context +": " + message); 
} 

public void fatalISE(String message) { 
    String context = "gather lots of information about the context of the error"; 
    throw new IllegalStateException(context +": " + message); 
} 

を交換することである。

public MyObject myMethod() { 
    if (allIsGood()) { 
     return new MyObject(); 
    } 
    return ErrorContext.fatalISE("all is not good"); 
} 

それはMyMethodはのどんな戻り値の型を動作しますプリミティブ型を含む。 fatalISEは、returnキーワードを使用しないで、voidメソッドで引き続き使用できます。

+2

これは賢明です(かなり巧妙です)が、コードを読んでいる人には誤解を招くことがあります。 –

+1

プリミティブではなく、参照を返す関数で動作するようです: 'の型パラメータは決定できません。 'return this.fatalISE(" blah ");' –

5

は終わり

return null; 

を追加します。 (それは決してそこに届くことはありませんが、コンパイラはこれを行う必要があります)

6

if条件を逆にするのはどうですか?

public MyObject myMethod() { 
    if (!allIsGood()) { 
     ErrorContext.fatalISE("all is not good"); 
    } 
    return new MyObject(); 
} 

幸運を祈る!

0

私はこのユースケースに遭遇しましたが、常に2つ以上のタイプの例外をスローする方法がありました。

コードをコンパイルするには、return null;を追加するとMouseEventと言います。

以上、null値を返す防ぐthrow new AssertionError()と交換し、読みやすさを改善し、誰かがcheckAndAlwaysThrowException()を変更した場合、それは常にスロー例外

public Object myMehtod() throws ExceptionType1, ExceptionType2 { 
    //.... 
    checkAndAlwaysThrowException(); 
    throw new AssertionError("checkAndAlwaysThrowException should have throw exception"); 
} 

public void checkAndAlwaysThrowException() throws ExceptionType1, ExceptionType2 { 
    if (cond) { 
     throw new ExceptionType1(); 
    } else { 
     throw new ExceptionType2(); 
    } 
} 
関連する問題