76

これは、今日同僚との議論で出てきました。

Java の Javadocs には、次のように記載IllegalStateExceptionされています。

メソッドが不正または不適切なタイミングで呼び出されたことを示します。つまり、Java 環境または Java アプリケーションは、要求された操作に適した状態ではありません。

また、Effective Java は次のように述べています (項目 60、248 ページ)。

よく再利用される別の例外は、IllegalStateException です。これは通常、受信オブジェクトの状態が原因で呼び出しが不正である場合にスローされる例外です。たとえば、これは、適切に初期化される前に呼び出し元が何らかのオブジェクトを使用しようとした場合にスローされる例外です。

ここは少しズレがあるようです。javadocs の 2 番目の文は、例外が Java 実行状態に関する非常に広範な条件を説明できるように聞こえますが、Effective Java の説明は、オブジェクトの状態の状態に特に関連する条件に使用されるように聞こえます。メソッドが呼び出されました。

JDK (コレクションなどMatcher) と Guava で見た使用法は、間違いなく、Effective Java が話しているカテゴリに分類されるようです (「このオブジェクトは、このメソッドを呼び出すことができない状態にあります」)。IllegalStateExceptionこれはの兄弟とも一致しているようIllegalArgumentExceptionです。

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

4

6 に答える 6

44

以下は、JDK でのこの例外の特に正当な使用法の 1 つです (参照: URLConnection.setIfModifiedSince(long)300 以上の他の使用法の中で:

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

例はかなり明確だと思います。オブジェクトが特定の状態 (「接続済み」) にある場合、一部の操作は呼び出されません。この場合、接続が確立されたときに、一部のプロパティを設定できません。

この例外は、クラスに時間の経過とともに変化する状態 (ステート マシン?) があり、一部のメソッドが無関係または不可能になる場合に特に役立ちます。、およびメソッドCarを持つクラスについて考えてみてください。2回、次々と電話をかけることはおそらく悪いことではありませんが、始動した車に燃料を供給することは確かに悪い考えです. つまり、車は間違った状態にあります。start()stop()fuel()start()

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

于 2012-10-02T21:09:39.053 に答える
5

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

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」ガイダンスと「Effective Java」ガイダンスの間に実際には区別がないことも示しています。Shutdown の実装方法により、JVM のシャットダウン状態は state と呼ばれるフィールドに格納されます。したがって、「状態」フィールドは受信オブジェクトの状態の一部であるため、いつ IllegalStateException を使用するかについての「有効な Java」ガイダンスにも適合します。受信オブジェクト (Shutdown) が間違った状態にあるため、IllegalStateException をスローします。

私の意見では、いつ IllegalStateException を使用するかについての 2 つの説明は一貫しています。効果的な Java の説明は、もう少し実用的です。それだけです。私たちのほとんどにとって、Java 環境全体の中で最も重要な部分は、現在作成しているクラスです。

于 2012-10-02T21:49:33.100 に答える
2

の使用法をIllegalStateException見れば、より適切であれば2番目に言うと思います。この例外は多くのパッケージで使用されています

  • java.net
  • java.nio
  • java.util
  • java.util.concurrent など

1 つの例を指定すると、キューが既にいっぱいの場合、ArrayBlockingQueue.addはこの例外をスローします。現在、オブジェクトの状態は満杯であり、不適切または不正な時間に呼び出されています

どちらも同じ意味だと思いますが、言葉遣いの違いです。

于 2012-10-02T21:13:42.033 に答える
1

ライブラリを指定すると、ユーザー コードが原因でバグが検出されるたびにIllegalStateExceptionorをスローする必要がありますが、ライブラリは、ライブラリ自体の実装が原因でバグを検出するたびに をスローする必要があります。IllegalArgumentExceptionAssertionError

たとえば、ライブラリのテストではIllegalStateException、メソッド呼び出しの順序が間違っていると、ライブラリが をスローすると予想される場合があります。しかし、ライブラリがAssertionError.

于 2016-04-02T07:54:55.930 に答える
0

ここに「矛盾」はありません。Bloch の文言には、JLS で述べられていることを除外するものは何もありません。Bloch は単に、状況 A がある場合、この例外をスローすると言っているだけです。彼は、この例外がこの状態でのみスローされる/スローされるべきだと言っているのではありません。JLS は、A、B、または C の場合にこの例外がスローされると言っています。

于 2012-10-03T00:00:41.200 に答える