Dies kam heute in einem Gespräch mit einem Kollegen zum Ausdruck.
Die Javadocs für Java IllegalStateException
geben an, dass es:
Signalisiert, dass eine Methode zu einem illegalen oder unangemessenen Zeitpunkt aufgerufen wurde. Mit anderen Worten, die Java-Umgebung oder Java-Anwendung befindet sich nicht in einem geeigneten Zustand für die angeforderte Operation.
Und Effective Java sagt (Punkt 60, Seite 248):
Eine weitere häufig wiederverwendete Ausnahme ist IllegalStateException. Dies ist im Allgemeinen die Ausnahme, die ausgelöst wird, wenn der Aufruf aufgrund des Status des empfangenden Objekts unzulässig ist. Dies wäre beispielsweise die Ausnahme, die ausgelöst werden muss, wenn der Aufrufer versucht hat, ein Objekt zu verwenden, bevor es ordnungsgemäß initialisiert wurde.
Es scheint, dass es hier ein bisschen Diskrepanz gibt. Der zweite Satz der Javadocs lässt es so klingen, als könnte die Ausnahme eine sehr breite Bedingung über den Java-Ausführungsstatus beschreiben, aber die Beschreibung in Effective Java lässt es so klingen, als würde es für Bedingungen verwendet, die sich speziell auf den Zustand des Zustands des Objekts beziehen, dessen Methode wurde aufgerufen.
Die Verwendungen, die ich im JDK (z. B. Sammlungen Matcher
) und in Guava gesehen habe, scheinen definitiv in die Kategorie zu fallen, über die Effective Java spricht ("Dieses Objekt befindet sich in einem Zustand, in dem diese Methode nicht aufgerufen werden kann"). Dies scheint auch im Einklang mit IllegalStateException
dem Geschwister zu stehen IllegalArgumentException
.
Gibt es IllegalStateException
im JDK legitime Verwendungen, die sich auf die "Java-Umgebung" oder die "Java-Anwendung" beziehen? Oder befürworten Best Practices-Anleitungen die Verwendung für den breiteren Ausführungsstatus? Wenn nicht, warum zum Teufel sind die Javadocs so formuliert? ;)
quelle
In Java, an exception that occurs when using multiple threads, whereby one thread modifies an object in a way that makes it incompatible with the use of that object in the second thread, thus putting the object into an illegal state.
. Huh? Woher kommt das?IllegalStateException
(entweder direkt oder weil Sie beispielsweise Guava verwenden). Wo ist die Diskrepanz?Antworten:
Hier ist eine besonders legitime Verwendung dieser Ausnahme in JDK (siehe:
URLConnection.setIfModifiedSince(long)
unter mehr als 300 anderen Verwendungen davon:public void setIfModifiedSince(long ifmodifiedsince) { if (connected) throw new IllegalStateException("Already connected"); ifModifiedSince = ifmodifiedsince; }
Ich denke, das Beispiel ist ziemlich klar. Wenn sich das Objekt in einem bestimmten Zustand befindet (" Bereits verbunden "), sollten einige Operationen nicht aufgerufen werden. In diesem Fall können beim Herstellen der Verbindung einige Eigenschaften nicht festgelegt werden.
Diese Ausnahme ist besonders nützlich, wenn Ihre Klasse einen Status (Statusmaschine?) Hat, der sich im Laufe der Zeit ändert und einige Methoden irrelevant oder unmöglich macht. Denken Sie an eine
Car
Klasse , die hatstart()
,stop()
undfuel()
Methoden. Wenn Siestart()
zweimal nacheinander anrufen , ist das wahrscheinlich nichts Falsches, aber das Betanken eines gestarteten Autos ist sicherlich eine schlechte Idee. Das Auto befindet sich nämlich in einem falschen Zustand.Eine wohl gute API sollte es uns nicht erlauben, Methoden im falschen Zustand aufzurufen, damit solche Probleme zur Kompilierungszeit und nicht zur Laufzeit entdeckt werden. In diesem Beispiel sollte das Herstellen einer Verbindung zu einer URL ein anderes Objekt mit einer Teilmenge von Methoden zurückgeben, die alle nach dem Herstellen einer Verbindung gültig sind.
quelle
IllegalArgumentException
Hier ist ein Beispiel im JDK. Es gibt eine private Paketklasse namens java.lang.Shutdown. Wenn das System heruntergefahren wird und Sie versuchen, einen neuen Hook hinzuzufügen, wird die IllegalStateException ausgelöst. Man könnte argumentieren, dass dies die Kriterien der "Javadoc" -Richtlinie erfüllt - da sich die Java-Umgebung im falschen Zustand befindet.
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; } }
Es zeigt jedoch auch, dass es wirklich keinen Unterschied zwischen der Anleitung "javadoc" und der Anleitung "Effective Java" gibt. Aufgrund der Art und Weise, wie Shutdown implementiert wird, wird das Herunterfahren der JVM in einem Feld namens state gespeichert. Daher erfüllt es auch die "Effective Java" -Richtlinie für die Verwendung von IllegalStateException, da das Feld "state" Teil des Status des empfangenden Objekts ist. Da sich das empfangende Objekt (Shutdown) im falschen Zustand befindet, wird die IllegalStateException ausgelöst.
Meiner Meinung nach sind die beiden Beschreibungen, wann IllegalStateException verwendet werden soll, konsistent. Die Beschreibung von Effective Java ist etwas praktischer, das ist alles. Für die meisten von uns ist der wichtigste Teil der gesamten Java-Umgebung die Klasse, die wir gerade schreiben. Darauf konzentriert sich der Autor.
quelle
InternalError
Wurf direkt unter der ISE zeigt auch, wie nützlich es ist, zwischen "Du hast es vermasselt" und "Ich habe es vermasselt" zu unterscheiden. Außerdem wird angezeigt, wie der statische Status (man könnte sagen "Java-Anwendung" oder "Java-Umgebung") für ISEs immer noch als Status zählt.AssertionError
wäre besser geeignet für Fälle, in denen ich weiß, dass ich es vermasselt habe. Es scheintInternalError
nur deshalb so zu sein, weil es sich eher im JDK-Code als im Anwendungscode befindet - eine zweifelhafte Unterscheidung.AssertionError
. es scheint zu vermitteln "Ich habe es vermasselt" im Gegensatz zu "Du hast es vermasselt" (was ISE impliziert). Ich benutze es oft in demdefault
Fall fürswitch
es. IMOInternalError
dient immer noch einem nützlichen Zweck; Die Person, die den Stack-Trace liest, weiß, dass sie "Whoa, das JDK hat es vermasselt" annehmen kann, aber die JDK-Autoren hätten es wahrscheinlich weglassen können.Ich denke, wenn Sie die Verwendung von sehen,
IllegalStateException
würde ich zweitens sagen, wenn es angemessener ist. Diese Ausnahme wird in vielen Paketen verwendetUm ein Beispiel anzugeben, löst ArrayBlockingQueue.add diese Ausnahme aus, wenn die Warteschlange bereits voll ist. Jetzt ist der Status des Objekts voll und es wird zu einem unangemessenen oder illegalen Zeitpunkt aufgerufen
Ich denke, beide bedeuten gleich, aber unterschiedliche Formulierungen.
quelle
Bei einer Bibliothek, soll es wirft eine
IllegalStateException
oder ,IllegalArgumentException
wenn es einen Fehler aufgrund des Benutzercode erkennt, während sollte die Bibliothek einen werfen ,AssertionError
wenn es aufgrund der Bibliothek eigener Implementierung eines Fehler erkennt.In den Tests der Bibliothek können Sie beispielsweise erwarten, dass die Bibliothek einen löst,
IllegalStateException
wenn die Reihenfolge der Methodenaufrufe falsch ist. Aber Sie werden nie erwarten, dass die Bibliothek eine wirftAssertionError
.quelle
Hier gibt es keine "Diskrepanz". In Blochs Wortlaut gibt es nichts, was ausschließt, was in der JLS steht. Bloch sagt einfach, wenn Sie Umstand A haben, werfen Sie diese Ausnahme. Er sagt nicht , dass diese Ausnahme nur in diesem Zustand ausgelöst wird / werden sollte . Das JLS sagt, dass diese Ausnahme ausgelöst wird, wenn A, B oder C.
quelle
Ich bin darauf gestoßen mit:
try { MessageDigest digest = MessageDigest.getInstance("SHA-1"); ... } catch (NoSuchAlgorithmException e) { throw new AssertionError(e); }
Ich denke, es wird für mich unpraktisch sein,
IllegalStateException
hier anstelle von zu werfenAssertionException
, obwohl dies in die Kategorie "Java-Umgebung" fällt.quelle