2012-10-02 22 views
63

これは今日の同僚とのディスカッションのなかに現れました。この方法は、違法または不適切なときに呼び出されましたIllegalStateExceptionの目的は何ですか?

シグナル:

JavaのIllegalStateException状態のJavadocそれという。言い換えれば、Java環境またはJavaアプリケーションは、要求された操作に適切な状態ではありません。

かつ効果的なJavaは言う(項目60、ページ248):

別の一般的な再利用の例外は、IllegalStateExceptionがあります。これは一般に、受信オブジェクトの状態のために呼び出しが不正である場合にスローする例外です。たとえば、呼び出し元が適切に初期化される前にオブジェクトを使用しようとすると、例外がスローされます。

ここには少し矛盾があるようです。 javadocの2番目の文は、例外がJavaの実行状態に関する非常に広い条件を記述できるように思えますが、Effective Javaの記述は、オブジェクトの状態の状態に特有の条件メソッドが呼び出されました。

JDK(コレクション、Matcherなど)やGuavaで使用されている使用法は、有効なJavaが話すカテゴリに該当するようです。「このオブジェクトはこのメソッドを呼び出すことができない状態です")。これはIllegalStateExceptionの兄弟IllegalArgumentExceptionと一貫しているようです。

「Java環境」または「Javaアプリケーション」に関連する合法的なIllegalStateExceptionの使用はJDKにありますか?または、ベストプラクティスガイドで広範な実行状態で使用することを推奨しますか?もしそうでなければ、なぜそのような言い方をしているjavadocは何ですか? ;ここでは)

+4

StackOverflowの[illegalstatexception]タグには、「Javaでは、複数のスレッドを使用すると例外が発生し、1つのスレッドがそのオブジェクトの使用と互換性のない方法でオブジェクトを変更するという例外がありますオブジェクトを違法な状態にすることになります。ハァッ?これはどこから来たのですか? –

+3

"Javaアプリケーション"はあなたが書いたものであり、そこに 'IllegalStateException'を直接(あるいはあなたがGuavaを使っているので)使うことができます。不一致はどこですか? –

+4

タグwikiが偽装しています。私はこの質問から自由に借用して編集を提出しました。ピアレビューに合格したら新しいバージョンが表示されます。 – meriton

答えて

35

は、JDKでこの例外の一つの特に合法的な使用方法である(参照:それの他の用途300+の中URLConnection.setIfModifiedSince(long)を:

public void setIfModifiedSince(long ifmodifiedsince) { 
    if (connected) 
     throw new IllegalStateException("Already connected"); 
    ifModifiedSince = ifmodifiedsince; 
} 

私は例がかなり明確だと思うオブジェクトが特定されている場合。

この例外は、クラスに何らかの状態(ステートマシン?)がある場合に特に便利です。ステートマシン( "既に接続されています")では、いくつかの操作は呼び出されません。 )時間がたつにつれて変化し、いくつかのメソッドをirrelevanにするtまたは不可能。 start()stop()fuel()のメソッドを持つCarクラスについて考えてみましょう。 start()を2回、1つずつ呼び出すのはおそらく間違っていませんが、始まった車に燃料を供給することは確かに悪い考えです。つまり、車は間違った状態です。

間違いなく良いAPIは、間違った状態のメソッドを呼び出さないようにして、実行時ではなくコンパイル時に問題が発見されるようにするべきではありません。この特定の例では、URLに接続すると、メソッドのサブセットを持つ別のオブジェクトが返されます。これらのメソッドはすべて、接続後に有効です。

+1

私はあなたの答えに同意します。しかし、これはなぜJavaとGuavaがこの例外を "IllegalArgumentException'のように使うのか説明していません – Zarathustra

0

IllegalStateExceptionの使用が表示されると思いますが、より適切な場合は2番目と言います。この例外は、パッケージ

  • java.net
  • java.nioの
  • java.utilの
  • がjava.util.concurrrentなど

は一例を指定するにはArrayBlockingQueue.addスローの多くで使用されていますキューがすでに満杯の場合はこの例外が発生します。今度はオブジェクトの状態が完全であり、不適切または不正な時間に呼び出されています

私はどちらも同じことを言いますが言葉の違いを思います。

4

次はJDKの例です。 java.lang.Shutdownというパッケージプライベートクラスがあります。システムがシャットダウンしていて、新しいフックを追加しようとすると、IllegalStateExceptionがスローされます。これは「javadoc」ガイダンスの基準を満たしていると主張することができます。これはJava環境が間違った状態にあるためです。

class Shutdown {  
... 

    /* Add a new shutdown hook. Checks the shutdown state and the hook itself, 
    * but does not do any security checks. 
    */ 
    static void add(int slot, Runnable hook) { 
     synchronized (lock) { 
      if (state > RUNNING) 
       throw new IllegalStateException("Shutdown in progress"); 

      if (hooks[slot] != null) 
       throw new InternalError("Shutdown hook at slot " + slot + " already registered"); 

      hooks[slot] = hook; 
     } 
    } 

ただし、「javadoc」ガイダンスと「効果的Java」ガイダンスの区別は実際にはありません。シャットダウンの実装方法のため、JVMのシャットダウンはstateと呼ばれるフィールドに格納されます。したがって、 "state"フィールドは受信オブジェクトの状態の一部であるため、IllegalStateExceptionをいつ使用するかについての "Effective Java"ガイダンスも満たしています。受信オブジェクト(Shutdown)の状態が間違っているため、IllegalStateExceptionがスローされます。

私の意見では、IllegalStateExceptionを使用するときの2つの記述は一貫しています。効果的なJavaの記述はもう少し実用的です。それだけです。私たちの大部分にとって、Java環境全体の中で最も重要な部分は、今作っているクラスなので、作者がそれに焦点を当てています。

+1

ああ、私はこの例が好きです! ISEの真下にある「InternalError」は、「あなたが大混乱している」と「私が混乱している」を区別することがどれほど有益であるかを示しています。また、ISEに関する限り、静的状態(「Javaアプリケーション」または「Java環境」状態とも言える)がどのように状態としてカウントされるかを示しています。 –

+0

@AndrewMcNamee「AssertionError」は、私がうんざりしていることが分かっている場合には、より適切なものだと思います。これはアプリケーションコードではなくJDKコードの内部にあるため、内部的なエラーであると思われます。 – Ramon

+0

うん、私は確かに 'AssertionError'について同意する; 「あなたがうんざりしている」(ISEが示唆している)とは対照的に、「私はうんざりしている」と伝えているようです。私は 'switch'の' default'のケースでそれをたくさん使っています。 IMO InternalErrorはまだ有用な目的を果たしています。スタックトレースを読んでいる人は、「Whoa、JDKが台無しになっている」と思うかもしれないが、JDKの作者はおそらくそれをやめた可能性があることを知っている。 –

0

ここに「不一致」はありません。ブロッホの言葉には、JLSで言うことを除外するものは何もありません。 Blochは、単に状況Aがある場合、この例外をスローすると言っています。彼はではなく、であり、この例外はこの状態でのみに投げられるべきであると言っています。私は私がしてもAssertionExceptionの代わりに、ここでIllegalStateExceptionをスローすることは非現実的になると思う

try { 
    MessageDigest digest = MessageDigest.getInstance("SHA-1"); 
    ... 
} catch (NoSuchAlgorithmException e) { 
    throw new AssertionError(e); 
} 

:JLSはA、B、またはC

+0

あなたはそれを言うことができると思います。しかし、一方で、彼が与えた状況とは異なる使用状況が意図されていた場合、あまり具体的ではないので意味がないかもしれません。言い換えれば、ISEが現在の "私にこのメソッドを呼び出しましたが、私はそれを行うことができる状態にはありません"という場合以外の状況で使用することを意図していた場合、ISEは有益ではないかもしれません。しかし確かに、私はここで髪を分けていると思う;) –

+0

@AndrewMcNamee私は*そう言った。あなたのコメントの残りの部分が何を意味するのかはわかりませんが、存在しない場合は不一致を作り出しています。あなたは論理的な誤りを犯している。 – EJP

0

は、私がこれに走った場合は、この例外がスローされると言っていますこれは「Java環境」カテゴリに分類されます。図書館を考える

0

それがユーザーコードに起因するバグを検出するたびに、それはライブラリの独自の実装に起因するバグを検出するたびにライブラリがAssertionErrorをスローする必要があり、一方、それは、IllegalStateExceptionまたはIllegalArgumentExceptionをスローする必要があります。

たとえば、ライブラリのテストでは、メソッド呼び出しの順序が間違っているとライブラリがIllegalStateExceptionをスローすることがあります。しかし、図書館がAssertionErrorを投げるとは決して期待できません。

関連する問題