Esto surgió hoy en una discusión con un colega.
Los Javadocs para Java IllegalStateException
afirman que:
Señala que se ha invocado un método en un momento ilegal o inapropiado. En otras palabras, el entorno Java o la aplicación Java no se encuentran en un estado apropiado para la operación solicitada.
Y Effective Java dice (artículo 60, página 248):
Otra excepción comúnmente reutilizada es IllegalStateException. Esta es generalmente la excepción a lanzar si la invocación es ilegal debido al estado del objeto receptor. Por ejemplo, esta sería la excepción a lanzar si la persona que llama intenta usar algún objeto antes de que se haya inicializado correctamente.
Parece que hay un poco de discrepancia aquí. La segunda oración de los javadocs hace que parezca que la excepción podría describir una condición muy amplia sobre el estado de ejecución de Java, pero la descripción en Java efectivo hace que parezca que se usa para condiciones relacionadas específicamente con el estado del estado del objeto cuyo se ha llamado al método.
Los usos que he visto en el JDK (por ejemplo, colecciones Matcher
) y en Guava definitivamente parecen caer en la categoría de la que habla Effective Java ("Este objeto está en un estado en el que no se puede llamar a este método"). Esto también parece consistente conIllegalStateException
el hermano de ' IllegalArgumentException
.
¿Hay IllegalStateException
usos legítimos en el JDK que se relacionen con el "entorno Java" o la "aplicación Java"? ¿O alguna guía de mejores prácticas aboga por su uso para el estado de ejecución más amplio? Si no es así, ¿por qué diablos están los javadocs redactados así? ;)
fuente
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.
. ¿Eh? ¿De donde viene esto?IllegalStateException
allí (ya sea directamente o porque está usando Guava, por ejemplo). ¿Dónde está la discrepancia?Respuestas:
Aquí hay un uso particularmente legítimo de esta excepción en JDK (ver:
URLConnection.setIfModifiedSince(long)
entre más de 300 usos de la misma:public void setIfModifiedSince(long ifmodifiedsince) { if (connected) throw new IllegalStateException("Already connected"); ifModifiedSince = ifmodifiedsince; }
Creo que el ejemplo es bastante claro. Si el objeto está en un estado particular (" Ya conectado "), algunas operaciones no deben llamarse. En este caso, cuando se estableció la conexión, no se pueden establecer algunas propiedades.
Esta excepción es especialmente útil cuando su clase tiene algún estado (¿máquina de estado?) Que cambia con el tiempo, haciendo que algunos métodos sean irrelevantes o imposibles. Pensar en una
Car
clase que tienestart()
,stop()
yfuel()
métodos. Si bien llamarstart()
dos veces, una tras otra, probablemente no sea nada malo, pero cargar combustible en un automóvil encendido es ciertamente una mala idea. Es decir, el coche está en mal estado.Podría decirse que una buena API no debería permitirnos llamar a métodos en un estado incorrecto para que problemas como ese se descubran en tiempo de compilación, no en tiempo de ejecución. En este ejemplo en particular, la conexión a una URL debería devolver un objeto diferente con un subconjunto de métodos, todos los cuales son válidos después de la conexión.
fuente
IllegalArgumentException
Aquí hay un ejemplo en el JDK. Hay un paquete de clase privada llamado java.lang.Shutdown. Si el sistema se está apagando e intenta agregar un nuevo gancho, lanza la IllegalStateException. Se podría argumentar que esto cumple con los criterios de la guía "javadoc", ya que es el entorno Java el que está en el estado incorrecto.
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; } }
Sin embargo, también ilustra que realmente no hay distinción entre la guía "javadoc" y la guía "Java efectivo". Debido a la forma en que se implementa el cierre, el cierre de la JVM se almacena en un campo llamado estado. Por lo tanto, también cumple con las pautas de "Java efectivo" sobre cuándo usar IllegalStateException, ya que el campo "estado" es parte del estado del objeto receptor. Dado que el objeto receptor (Shutdown) está en un estado incorrecto, lanza la IllegalStateException.
En mi opinión, las dos descripciones de cuándo usar IllegalStateException son consistentes. La descripción de Effective Java es un poco más práctica, eso es todo. Para la mayoría de nosotros, la parte más importante de todo el entorno Java es la clase que estamos escribiendo en este momento, por lo que el autor se centra en eso.
fuente
InternalError
tiro justo debajo del ISE también demuestra lo útil que es hacer una distinción entre "Lo arruinaste" y "Yo lo arruiné". Además, muestra cómo el estado estático (podría decir "Aplicación Java" o estado "Entorno Java") todavía cuenta como estado en lo que respecta a los ISE.AssertionError
sería más apropiado para los casos en los que sé que me equivoqué. Parece serInternalError
solo porque está dentro del código JDK en lugar del código de la aplicación, una distinción dudosa.AssertionError
; parece transmitir "Me equivoqué" en contraposición a "Tú lo arruinaste" (lo que implica ISE). Lo uso mucho en eldefault
caso deswitch
es. La OMIInternalError
todavía tiene un propósito útil; la persona que lee el seguimiento de la pila sabe que puede asumir "Whoa, el JDK se equivocó", pero los autores del JDK probablemente podrían haberlo omitido.Supongo que si ve el uso de
IllegalStateException
, diría segundo si es más apropiado. Esta excepción se utiliza en muchos paquetes.Para especificar un ejemplo, ArrayBlockingQueue.add lanza esta excepción si la cola ya está llena. Ahora lleno es el estado del objeto y se está invocando en un momento inapropiado o ilegal.
Supongo que ambos significan lo mismo pero con diferencias de redacción.
fuente
Dada una biblioteca, debería lanzar un
IllegalStateException
oIllegalArgumentException
siempre que detecte un error debido al código de usuario, mientras que la biblioteca debería lanzar unAssertionError
cada vez que detecte un error debido a la propia implementación de la biblioteca.Por ejemplo, en las pruebas de la biblioteca, puede esperar que la biblioteca arroje un
IllegalStateException
error cuando el orden de las llamadas al método sea incorrecto. Pero nunca esperará que la biblioteca arroje unAssertionError
.fuente
No hay ninguna "discrepancia" aquí. No hay nada en la redacción de Bloch que excluya lo que dice en la JLS. Bloch simplemente está diciendo que si tienes la circunstancia A, lanza esta excepción. Él es no decir que esta excepción es / debe ser tirado solamente en esta condición. El JLS dice que esta excepción se lanza si A, B o C.
fuente
Me encontré con esto con:
try { MessageDigest digest = MessageDigest.getInstance("SHA-1"); ... } catch (NoSuchAlgorithmException e) { throw new AssertionError(e); }
Creo que no será práctico para mí
IllegalStateException
colocarlo aquí en lugar deAssertionException
aunque esto se encuentre en la categoría "el entorno Java".fuente