traducir sale porque pointer catch java exception null nullpointerexception illegalargumentexception

java - sale - ¿IllegalArgumentException o NullPointerException para un parámetro nulo?



nullpointerexception processing (26)

Tengo un método de establecimiento simple para una propiedad y null no es apropiado para esta propiedad en particular. Siempre he estado desgarrado en esta situación: ¿debería lanzar una IllegalArgumentException o una NullPointerException ? Desde los javadocs, ambos parecen apropiados. ¿Hay algún tipo de estándar entendido? ¿O es esto solo una de esas cosas que debes hacer lo que prefieras y ambas son realmente correctas?


Debes lanzar una excepción IllegalArgumentException, ya que le hará obvio al programador que ha hecho algo inválido. Los desarrolladores están tan acostumbrados a ver la NPE lanzada por la máquina virtual, que cualquier programador no se daría cuenta inmediatamente de su error, y comenzaría a buscar aleatoriamente, o peor, culparía a su código por estar "lleno de errores".


En este caso, IllegalArgumentException transmite información clara al usuario mediante su API de que "no debe ser nulo". Como otros usuarios del foro señalaron, usted podría usar NPE si lo desea, siempre y cuando transmita la información correcta al usuario utilizando su API.

GaryF y tweakt eliminaron las referencias de "Java efectiva" (que juro por) que recomiendan el uso de NPE. Y observar cómo se construyen otras API buenas es la mejor manera de ver cómo construir su API.

Otro buen ejemplo es mirar las API de Spring. Por ejemplo, org.springframework.beans.BeanUtils.instantiateClass (constructor ctor, objeto [] args) tiene una línea Assert.notNull (ctor, "El constructor no debe ser nulo"). El método org.springframework.util.Assert.notNull (objeto Object, String message) comprueba si el argumento (objeto) pasado es nulo y si lanza un nuevo IllegalArgumentException (mensaje) que luego queda atrapado en la organización. Springframework.beans.BeanUtils.instantiateClass (...) método.


Idealmente, las excepciones de tiempo de ejecución no se deberían lanzar. Se debe crear una excepción marcada (excepción de negocios) para su escenario. Debido a que si cualquiera de estas excepciones se lanza y se registra, se desvía del desarrollador al pasar por los registros. En su lugar, las excepciones comerciales no crean ese pánico y, por lo general, se ignoran al solucionar problemas de los registros.


Las definiciones de los enlaces a las dos excepciones anteriores son IllegalArgumentException: lanzadas para indicar que un método ha pasado un argumento ilegal o inapropiado. NullPointerException: se lanza cuando una aplicación intenta utilizar null en un caso en el que se requiere un objeto.

La gran diferencia aquí es que se supone que IllegalArgumentException se usa cuando se comprueba que un argumento de un método es válido. Se supone que NullPointerException se utiliza cuando un objeto se "usa" cuando es nulo.

Espero que ayude a poner los dos en perspectiva.


NullPointerException lanzada al intentar acceder a un objeto con una variable de referencia cuyo valor actual es nulo

Se genera IllegalArgumentException cuando un método recibe un argumento con un formato diferente al que el método espera.


Según su escenario, IllegalArgumentException es la mejor opción, ya null que no es un valor válido para su propiedad.


Si elige lanzar un NPE y está utilizando el argumento en su método, puede ser redundante y costoso verificar explícitamente si hay un nulo. Creo que la máquina virtual ya hace eso por ti.


Si es un "configurador", o en algún lugar que consiga que un miembro use más adelante, tiendo a usar IllegalArgumentException.

Si es algo que voy a usar (desreferenciación) en este momento en el método, lanzo una NullPointerException proactivamente. Me gusta esto más que dejar que el tiempo de ejecución lo haga, porque puedo proporcionar un mensaje útil (parece que el tiempo de ejecución también podría hacerlo, pero eso es una perorata para otro día).

Si estoy anulando un método, uso lo que use el método anulado.


Algunas colecciones asumen que el null se rechaza utilizando la IllegalArgumentException NullPointerException lugar de IllegalArgumentException . Por ejemplo, si compara un conjunto que contiene un valor null con un conjunto que rechaza el null , el primer conjunto llamará a los containsAll IllegalArgumentException en el otro y capturará su excepción NullPointerException , pero no IllegalArgumentException . (Estoy mirando la implementación de AbstractSet.equals .)

Podría razonablemente argumentar que el uso de excepciones no verificadas de esta manera es un antipatrón, que comparar colecciones que contienen null colecciones que no pueden contener null es un error probable que realmente debería producir una excepción, o que poner null una colección es una mala idea. . Sin embargo, a menos que esté dispuesto a decir que equals debería lanzar una excepción en tal caso, está atascado recordando que NullPointerException se requiere en ciertas circunstancias pero no en otras. ("IAE antes de NPE excepto después de ''c'' ...")


Apache Commons Lang tiene una NullArgumentException que hace varias de las cosas que se tratan aquí: extiende IllegalArgumentException y su único constructor toma el nombre del argumento que debería haber sido no nulo.

Si bien creo que lanzar algo como una NullArgumentException o IllegalArgumentException describe con mayor precisión las circunstancias excepcionales, mis colegas y yo hemos optado por seguir el consejo de Bloch sobre el tema.


Como una pregunta subjetiva, esto debería cerrarse, pero como sigue abierto:

Esto es parte de la política interna utilizada en mi anterior lugar de trabajo y funcionó muy bien. Esto es todo de memoria, así que no puedo recordar la redacción exacta. Vale la pena señalar que no usaron excepciones marcadas, pero eso está más allá del alcance de la pregunta. Las excepciones sin marcar que utilizaron se dividieron en 3 categorías principales.

NullPointerException: No lanzar intencionalmente. Las NPE deben ser lanzadas solo por la máquina virtual cuando se elimina la referencia a una referencia nula. Se deben hacer todos los esfuerzos posibles para garantizar que nunca se tiren. @Nullable y @NotNull deben usarse junto con las herramientas de análisis de código para encontrar estos errores.

IllegalArgumentException: se lanza cuando un argumento de una función no se ajusta a la documentación pública, de manera que el error se puede identificar y describir en términos de los argumentos que se pasaron. La situación del OP se incluiría en esta categoría.

IllegalStateException: se lanza cuando se llama a una función y sus argumentos son inesperados en el momento en que se pasan o son incompatibles con el estado del objeto del que es miembro el método.

Por ejemplo, hubo dos versiones internas de la excepción IndexOutOfBoundsException usadas en cosas que tenían una longitud. Una subclase de IllegalStateException, utilizada si el índice era mayor que la longitud. La otra, una subclase de IllegalArgumentException, se utiliza si el índice es negativo. Esto se debió a que podría agregar más elementos al objeto y el argumento sería válido, mientras que un número negativo nunca es válido.

Como dije, este sistema funciona realmente bien, y fue necesario que alguien explicara por qué existe la distinción: "Dependiendo del tipo de error, es bastante sencillo para usted averiguar qué hacer. Incluso si realmente no puede calcularlo. lo que salió mal, puede averiguar dónde detectar ese error y crear información de depuración adicional ".

NullPointerException: Maneja el caso Null o coloca una aserción para que el NPE no se lance. Si pones una aserción es solo uno de los otros dos tipos. Si es posible, continúe con la depuración como si la afirmación estuviera allí en primer lugar.

IllegalArgumentException: tiene un error en su sitio de llamada. Si los valores que se pasan son de otra función, averigüe por qué está recibiendo un valor incorrecto. Si está pasando uno de sus argumentos, el error verifica la pila de llamadas hasta que encuentre la función que no está devolviendo lo que esperaba.

IllegalStateException: no ha llamado a sus funciones en el orden correcto. Si está utilizando uno de sus argumentos, verifíquelos y lance una excepción IllegalArgumentException que describa el problema. Luego puedes propagar las mejillas contra la pila hasta que encuentres el problema.

De todos modos, su punto era que solo puedes copiar las IlegalArgumentAssertions en la pila. No hay forma de propagar las IllegalStateExceptions o NullPointerExceptions en la pila porque tenían algo que ver con su función.


Debería usar IllegalArgumentException (IAE), no NullPointerException (NPE) por los siguientes motivos:

Primero, la NPE JavaDoc enumera explícitamente los casos en los que la NPE es apropiada. Tenga en cuenta que todos ellos son lanzados por el tiempo de ejecución cuando el null se utiliza de forma inadecuada. En contraste, el IAE JavaDoc no podría ser más claro: "Lanzado para indicar que un método ha pasado un argumento ilegal o inapropiado". Sí, esa eres tú!

En segundo lugar, cuando ve un NPE en un seguimiento de pila, ¿qué asume? Probablemente ese alguien hizo referencia a un null . Cuando ve IAE, asume que la persona que llama al método en la parte superior de la pila pasa un valor ilegal. Una vez más, el último supuesto es cierto, el primero es engañoso.

Tercero, dado que IAE está claramente diseñado para validar parámetros, debe asumirlo como la opción predeterminada de excepción, ¿por qué elegir NPE? Ciertamente, no para comportamientos diferentes: ¿realmente espera que el código de llamada capture los NPE por separado de IAE y haga algo diferente como resultado? ¿Estás tratando de comunicar un mensaje de error más específico? Pero puede hacerlo en el texto del mensaje de excepción de todos modos, como debería hacer con todos los demás parámetros incorrectos.

Cuarto, todos los demás datos de parámetros incorrectos serán IAE, entonces ¿por qué no ser consistentes? ¿Por qué es que un null ilegal es tan especial que merece una excepción separada de todos los otros tipos de argumentos ilegales?

Finalmente, acepto el argumento dado por otras respuestas de que partes de la API de Java usan NPE de esta manera. Sin embargo, la API de Java no es coherente con todo, desde los tipos de excepción hasta las convenciones de nomenclatura, por lo que creo que copiar ciegamente (su parte favorita) la API de Java no es un argumento lo suficientemente bueno como para superar estas otras consideraciones.


El estándar es lanzar la NullPointerException . El "Java efectivo" generalmente infalible lo analiza brevemente en el Artículo 42 (primera edición), Artículo 60 (segunda edición) o Artículo 72 (tercera edición) "Favorecer el uso de excepciones estándar":

"Podría decirse que todas las invocaciones erróneas de métodos se reducen a un argumento ilegal o estado ilegal, pero normalmente se usan otras excepciones para ciertos tipos de argumentos y estados ilegales. Si una persona que llama pasa nulo en algún parámetro para el cual los valores nulos están prohibidos, la convención dicta que "NullPointerException se lanzará en lugar de IllegalArgumentException".


En general, un desarrollador nunca debe lanzar una NullPointerException. Esta excepción es lanzada por el tiempo de ejecución cuando el código intenta eliminar la referencia a una variable cuyo valor es nulo. Por lo tanto, si su método quiere desautorizar explícitamente el valor nulo, en lugar de simplemente tener un valor nulo elevar una excepción NullPointerException, debe lanzar una excepción IllegalArgumentException.


En realidad, la cuestión de lanzar IllegalArgumentException o NullPointerException es, en mi opinión humilde, solo una "guerra santa" para una minoría con un entendimiento incompleto del manejo de excepciones en Java. En general, las reglas son simples, y como sigue:

  • las violaciones de restricciones de argumentos deben indicarse lo más rápido posible (-> falla rápida), para evitar estados ilegales que son mucho más difíciles de depurar
  • en caso de un puntero nulo no válido por cualquier razón, lance NullPointerException
  • en el caso de un índice de matriz / colección ilegal, lance ArrayIndexOutOfBounds
  • en el caso de un tamaño de matriz / colección negativo, lance NegativeArraySizeException
  • en caso de un argumento ilegal que no esté cubierto por lo anterior, y para el cual no tiene otro tipo de excepción más específico, lance la excepción IllegalArgumentException como papelera
  • por otro lado, en el caso de una violación de restricción DENTRO DE UN CAMPO que no pueda evitarse por un fallo rápido por algún motivo válido, reténgalo y vuelva a realizarlo como IllegalStateException o una excepción comprobada más específica. ¡Nunca deje pasar la excepción NullPointerException, ArrayIndexOutOfBounds original, etc. en este caso!

Existen al menos tres razones muy buenas contra el caso de mapear todo tipo de violaciones de restricciones de argumentos a IllegalArgumentException, y la tercera probablemente sea tan grave como para marcar el estilo incorrecto de la práctica:

(1) Un programador no puede asumir con seguridad que todos los casos de violaciones de restricciones de argumentos dan como resultado la excepción IllegalArgumentException, porque la gran mayoría de las clases estándar usan esta excepción en lugar de una papelera si no hay un tipo de excepción más específico disponible. Tratar de asignar todos los casos de violaciones de restricciones de argumentos a IllegalArgumentException en su API solo conduce a la frustración del programador al usar sus clases, ya que las bibliotecas estándar en su mayoría siguen diferentes reglas que infringen las suyas, ¡y la mayoría de los usuarios de API también las usarán!

(2) La asignación de las excepciones en realidad da como resultado un tipo diferente de anomalía, causada por una herencia única: todas las excepciones de Java son clases y, por lo tanto, solo admiten la herencia individual. Por lo tanto, no hay forma de crear una excepción que realmente diga una excepción NullPointerException y una IllegalArgumentException, ya que las subclases solo pueden heredar de una u otra. Lanzar una IllegalArgumentException en caso de un argumento nulo hace que sea más difícil para los usuarios de la API distinguir entre los problemas cada vez que un programa intenta corregir el problema mediante programación, por ejemplo, introduciendo los valores predeterminados en una repetición de llamada.

(3) La asignación en realidad crea el peligro de enmascaramiento de errores: para asignar las violaciones de restricción de argumento en la excepción IllegalArgumentException, deberá codificar un try-catch externo dentro de cada método que tenga argumentos restringidos. Sin embargo, la simple captura de RuntimeException en este bloque catch está fuera de discusión, ya que corre el riesgo de mapear las RuntimeExceptions documentadas generadas por los métodos de libery utilizados en el suyo en IllegalArgumentException, incluso si no están causadas por violaciones de restricciones de argumentos. Por lo tanto, debe ser muy específico, pero incluso ese esfuerzo no lo protege del caso de que asigne accidentalmente una excepción de tiempo de ejecución no documentada de otra API (es decir, un error) a una excepción IllegalArgumentException de su API. Por lo tanto, incluso el mapeo más cuidadoso corre el riesgo de enmascarar los errores de programación de otros creadores de bibliotecas, ya que los argumentos restringen las violaciones de los usuarios de su método, ¡lo que es simplemente un comportamiento terrible!

Por otra parte, con la práctica estándar, las reglas son simples y las causas de excepción permanecen desenmascaradas y específicas. Para el invocador del método, las reglas también son fáciles: - si encuentra una excepción de tiempo de ejecución documentada de cualquier tipo porque pasó un valor ilegal, repita la llamada con un valor predeterminado (para estas excepciones específicas son necesarias), o corrija su código - si, por otro lado, encuentra una excepción de tiempo de ejecución que no está documentada para un conjunto dado de argumentos, presente un informe de error a los fabricantes del método para asegurarse de que su código o su documentación sea corregido.


Es una pregunta de estilo de "Guerra Santa". En otras palabras, ambas alternativas son buenas, pero las personas tendrán sus preferencias que defenderán hasta la muerte.


Estaba a favor de lanzar IllegalArgumentException para parámetros nulos, hasta hoy, cuando noté el método java.util.Objects.requireNonNull en Java 7. Con ese método, en lugar de hacerlo:

if (param == null) { throw new IllegalArgumentException("param cannot be null."); }

tu puedes hacer:

Objects.requireNonNull(param);

y lanzará una NullPointerException si el parámetro que se pasa es null .

Dado que ese método es correcto en medio de java.util , tomo su existencia como una indicación bastante clara de que lanzar NullPointerException es "la forma Java de hacer las cosas".

Creo que estoy decidido en cualquier caso.

Tenga en cuenta que los argumentos sobre la depuración de errores son falsos porque, por supuesto, puede proporcionar un mensaje a NullPointerException que NullPointerException qué era nulo y por qué no debería ser nulo. Al igual que con IllegalArgumentException .

Una ventaja adicional de NullPointerException es que, en un código crítico de alto rendimiento, puede prescindir de una comprobación explícita de null (y de una NullPointerException con un mensaje de error), y basarse en la NullPointerException que obtendrá automáticamente cuando llame a un método. en el parámetro nulo. Siempre que llame a un método rápidamente (es decir, falle rápido), tendrá el mismo efecto, pero no es tan fácil de usar para el desarrollador. Es probable que la mayoría de las veces sea mejor verificar explícitamente y lanzar un mensaje útil para indicar qué parámetro fue nulo, pero es bueno tener la opción de cambiar eso si el desempeño lo dicta sin romper el contrato publicado del método / constructor.


La dicotomía ... ¿Son no superpuestas? Solo las partes no superpuestas de un todo pueden hacer una dicotomía. Como yo lo veo:

throw new IllegalArgumentException(new NullPointerException(NULL_ARGUMENT_IN_METHOD_BAD_BOY_BAD));


La práctica aceptada es usar la excepción IllegalArgumentException (mensaje de cadena) para declarar que un parámetro no es válido y dar tantos detalles como sea posible ... Entonces, para decir que se encontró que los parámetros eran nulos y no eran nulos, se haría algo Me gusta esto:

if( variable == null ) throw new IllegalArgumentException("The object ''variable'' cannot be null");

Prácticamente no tiene motivos para utilizar implícitamente la "excepción NullPointerException". La excepción NullPointerException es una excepción lanzada por la máquina virtual de Java cuando intenta ejecutar código en referencia nula (como toString () ).


Lanzar una excepción que sea exclusiva de argumentos null (ya sea una excepción NullPointerException o un tipo personalizado) hace que null pruebas null automatizadas sean más confiables. Esta prueba automatizada se puede hacer con reflexión y un conjunto de valores predeterminados, como en el NullPointerTester Guava . Por ejemplo, NullPointerTester intentará llamar al siguiente método ...

Foo(String string, List<?> list) { checkArgument(string.length() > 0); // missing null check for list! this.string = string; this.list = list; }

... con dos listas de argumentos: "", null y null, ImmutableList.of() . Se probaría que cada una de estas llamadas arroja la NullPointerException esperada. Para esta implementación, pasar una lista null no produce NullPointerException . Sin embargo, sucede que produce una IllegalArgumentException porque NullPointerTester usa una cadena predeterminada de "" . Si NullPointerTester espera solo NullPointerException para valores null , detecta el error. Si espera IllegalArgumentException , la pierde.


No podría estar más de acuerdo con lo que se está diciendo. Falla temprano, falla rápido Bastante buen mantra de excepción.

La pregunta sobre qué Excepción lanzar es principalmente una cuestión de gusto personal. En mi opinión, IllegalArgumentException parece más específico que usar una NPE ya que me dice que el problema fue con un argumento que pasé al método y no con un valor que se haya generado al realizar el método.

Mis 2 centavos


Parece que se IllegalArgumentException una IllegalArgumentException si no desea que el null sea ​​un valor permitido, y la NullPointerException emitiría si estuviera tratando de usar una variable que resulta ser null .


Quería destacar los argumentos nulos de otros argumentos ilegales, por lo que obtuve una excepción de IAE llamada NullArgumentException. Sin siquiera necesitar leer el mensaje de excepción, sé que se pasó un argumento nulo a un método y al leer el mensaje, descubro qué argumento era nulo. Todavía detecto la NullArgumentException con un controlador IAE, pero en mis registros es donde puedo ver la diferencia rápidamente.


Si se trata de un método de establecimiento y se le pasa un null , creo que tendría más sentido lanzar una IllegalArgumentException . Una NullPointerException parece tener más sentido en el caso de que intentes utilizar el null .

Entonces, si lo estás usando y es null , NullPointer . Si se está pasando y es null , IllegalArgument .


Tiendo a seguir el diseño de las bibliotecas JDK, especialmente Colecciones y concurrencia (Joshua Bloch, Doug Lea, esos tipos saben cómo diseñar API sólidas). De todos modos, muchas API en el JDK proactivamente NullPointerException .

Por ejemplo, el Javadoc para Map.containsKey indica:

@ throws NullPointerException si la clave es nula y este mapa no permite claves nulas (opcional).

Es perfectamente válido lanzar tu propia NPE. La convención es incluir el nombre del parámetro que estaba nulo en el mensaje de la excepción.

El patrón va:

public void someMethod(Object mustNotBeNull) { if (mustNotBeNull == null) { throw new NullPointerException("mustNotBeNull must not be null"); } }

Hagas lo que hagas, no permitas que se establezca un valor incorrecto y lanzas una excepción más adelante cuando otro código intente usarlo. Eso hace que la depuración de una pesadilla. Siempre debe seguir el principio de "fallar rápido".


Voto el argumento de Jason Cohen porque estaba bien presentado. Déjame desmembrarlo paso a paso. ;-)

  • El NPE JavaDoc dice explícitamente, "otros usos ilegales del objeto nulo" . Si se limitara a situaciones en las que el tiempo de ejecución encuentra un valor nulo cuando no debería, todos estos casos podrían definirse de manera mucho más sucinta.

  • No puede evitarlo si asume algo incorrecto, pero suponiendo que la encapsulación se aplica correctamente, realmente no debería preocuparse ni darse cuenta si un nulo se eliminó de forma inapropiada frente a si un método detectó un nulo inadecuado y desactivó una excepción.

  • Elegiría NPE sobre IllegalArgumentException por múltiples razones

    • Es más específico sobre la naturaleza de la operación ilegal.
    • La lógica que erróneamente permite nulos tiende a ser muy diferente de la lógica que erróneamente permite valores ilegales. Por ejemplo, si estoy validando los datos ingresados ​​por un usuario, si obtengo un valor que es inaceptable, la fuente de ese error es el usuario final de la aplicación. Si obtengo un nulo, es un error del programador.
    • Los valores no válidos pueden provocar desbordamientos de pila, errores de memoria, excepciones de análisis, etc. De hecho, la mayoría de los errores generalmente se presentan, en algún momento, como un valor no válido en una llamada de método. Por esta razón, veo a IAE como el MÁS GENERAL de todas las excepciones bajo RuntimeException.
  • En realidad, otros argumentos no válidos pueden dar como resultado todo tipo de excepciones. UnknownHostException , FileNotFoundException , una variedad de excepciones de errores de sintaxis, IndexOutOfBoundsException , fallas de autenticación, etc., etc.

En general, siento que la NPE es muy difamada porque tradicionalmente se ha asociado con un código que no sigue el principio de falla rápida . Eso, más el fracaso del JDK en poblar las NPE con una cadena de mensajes realmente ha creado un fuerte sentimiento negativo que no está bien fundado. De hecho, la diferencia entre NPE y IAE desde una perspectiva de tiempo de ejecución es estrictamente el nombre. Desde esa perspectiva, cuanto más preciso sea el nombre, más claridad le dará al interlocutor.