java - expected - ¿Cuál es el uso previsto de IllegalStateException?
java.lang.illegalstateexception expected begin_object but was string at line 1 column 1 path $ (6)
Aquí hay un ejemplo en el JDK. Hay una clase privada de paquete llamada java.lang.Shutdown. Si el sistema se está cerrando e intenta agregar un nuevo enlace, arroja la IllegalStateException. Se podría argumentar que esto cumple con los criterios de la guía "javadoc", ya que es el entorno de 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 existe distinción entre la orientación "javadoc" y la orientación "Java efectiva". Debido a la forma en que se implementa Shutdown, el apagado de la JVM se almacena en un campo llamado estado. Por lo tanto, también cumple con la guía "Effective Java" para cuándo usar IllegalStateException, ya que el campo "state" es parte del estado del objeto receptor. Dado que el objeto de recepción (Apagado) está en el estado incorrecto, arroja 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 de Java es la clase que estamos escribiendo en este momento, por lo que el autor se está centrando en eso.
Esto surgió en una discusión con un colega hoy.
La excepción IllegalStateException de Javadocs para Java lo IllegalStateException
:
Señala que un método ha sido invocado 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 Efectivo Java dice (Artículo 60, página 248):
Otra excepción comúnmente reutilizada es IllegalStateException. En general, esta es la excepción a throw si la invocación es ilegal debido al estado del objeto receptor. Por ejemplo, esta sería la excepción para tirar si la persona que llama intenta utilizar 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 suene como si se usara para condiciones relacionadas específicamente con el estado del objeto cuyo método ha sido llamado.
Los usos que he visto en el JDK (por ejemplo, colecciones, Matcher
) y en Guava definitivamente parecen pertenecer a la categoría sobre la que habla Effective Java ("Este objeto se encuentra en un estado donde no se puede llamar a este método"). Esto también parece consistente con la IllegalStateException
IllegalArgumentException
.
¿Hay algún uso legítimo de IllegalStateException
en el JDK que se relacione con el "entorno Java" o la "aplicación Java"? ¿O alguna guía de mejores prácticas recomienda usarla para un estado de ejecución más amplio? Si no, ¿por qué demonios son los javadocs redactados así? ;)
Aquí hay un uso particularmente legítimo de esta excepción en JDK (ver: URLConnection.setIfModifiedSince(long)
entre más de 300 usos más:
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 está conectado "), algunas operaciones no deben ser llamadas. En este caso, cuando se estableció la conexión, algunas propiedades no se pueden establecer.
Esta excepción es especialmente útil cuando su clase tiene algún estado (¿máquina de estado?) Que cambia con el tiempo, lo que hace que algunos métodos sean irrelevantes o imposibles. Piensa en una clase de Car
que tenga los métodos start()
, stop()
y fuel()
. Si llama a start()
dos veces, una detrás de otra, probablemente no sea nada incorrecto, pero alimentar un automóvil puesto en marcha ciertamente es una mala idea. A saber, el automóvil está en un estado equivocado.
Podría decirse que una buena API no debería permitirnos llamar a los métodos en estado incorrecto para que los problemas como ese se descubran en tiempo de compilación, no en tiempo de ejecución. En este ejemplo particular, la conexión a una URL debe devolver un objeto diferente con un subconjunto de métodos, todos los cuales son válidos después de la conexión.
Dada una biblioteca, debería arrojar una IllegalStateException
o IllegalArgumentException
siempre que detecte un error debido al código de usuario, mientras que la biblioteca debería arrojar un AssertionError
siempre 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 una IllegalStateException
cuando el orden de las llamadas al método es incorrecto. Pero nunca esperarás que la biblioteca arroje un AssertionError
.
Me encontré con esto con:
try {
MessageDigest digest = MessageDigest.getInstance("SHA-1");
...
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
Creo que no sería práctico para mí lanzar IllegalStateException
aquí en lugar de AssertionException
, aunque esto caiga en la categoría "el entorno de Java".
No hay ''discrepancia'' aquí. No hay nada en la redacción de Bloch que excluya lo que dice en el JLS. Bloch simplemente dice que si tienes la circunstancia A, lanza esta excepción. Él no está diciendo que esta excepción es / debería ser arrojada solo en esta condición. El JLS dice que esta excepción se produce si A, B o C.
Supongo que si ves el uso de IllegalStateException
, diría que es el segundo si es más apropiado. Esta excepción se usa en muchos paquetes
- java.net
- java.nio
- java.util
- java.util.concurrrent, etc.
Para especificar un ejemplo, ArrayBlockingQueue.add arroja esta excepción si la cola ya está llena. Ahora lleno es estado del objeto y se invoca en el momento inadecuado o ilegal
Supongo que ambos significan lo mismo, pero la diferencia de redacción.