2012-01-26 15 views
8

A menudo veo java SourceCode donde no se permite un valor nulo como valor para un método o constructor. Una aplicación típica de esto parece¿Tiene sentido realizar una autoverificación de nulo en Java

public void someMethod(Object someObject){ 

    if(someObject == null) throw new NullPointerException() 

    someObject.aMethodCall() 

} 

veo ningún sentido para mí en eso en absoluto, porque si intenta llamar a un método en un NullPointer la NullPointerException se tira de todos modos. Me gustaría ver un sentido si este método arrojaría una IllegalArgumentException o alguna otra excepción hecha a medida. ¿Puede alguien aclarar, por qué este cheque parece tener sentido (como lo veo muy a menudo estoy asumiendo, que tiene que haber sentido detrás de eso), o por qué es un completo sinsentido

+0

Esto es inútil si el comportamiento correcto es anular el puntero (de hecho, es peor ya que la verificación lleva un tiempo pequeño). – Jim

+0

Las comprobaciones nulas explícitas son tan baratas como las verificaciones nulas implícitas después de JIT, por lo que no me preocuparía el rendimiento aquí. –

+0

Posible duplicado: http://stackoverflow.com/questions/32280/passing-null-to-a-method Prefiero las afirmaciones para la comprobación de la bondad de los parámetros, al igual que las condiciones previas se usan en Ada. – vulkanino

Respuesta

9

El código que ha publicado no tiene absolutamente ningún sentido. Parece un caso fuerte de cargo cult programming. Lo más probable es que alguien haya implementado una prueba útil para verificar las precondiciones una vez y que otra persona haya adaptado la prueba para que se vea así.

4

Esto depende de quién es responsable de recuperar de esta situación. Si es la persona que llama, lanza un NPE. Si es el método llamado, pruebe null y haga lo que sea necesario para resolver la situación.

Edit: No arroje un NPE explícitamente sino simplemente déjelo burbujear. Perdón por la redacción vaga.

+0

Pero en el caso del ejemplo que dio el OP, está claro que el método en sí no se está recuperando de la excepción ... – cdeszaq

+0

Cierto, pero tomé esto solo como un MWE, no como un código real. –

+0

Lanzar una excepción sin marcar es una mala práctica de programación ... –

5

No, eso no tiene mucho sentido tal como está, pero solo porque lanzar una NPE no agrega ninguna información útil.

usted podría hacer más agradable el error lanzando (por ejemplo) un IllegalStateException:

if (someObject == null) throw new IllegalStateException("someObject was null"); 

Pero eso no quiere añadir un gran valor, ya sea - aparte de ser específico acerca de lo que es nula (que puede ser útil en métodos más complejos)

+0

Y la posible excepción debe declararse en la cláusula 'throws' y documentarse. –

5

Por supuesto que desea comprobar nulo. Esta es una condición previa para su método, parte de su contrato con los clientes. Si su método no puede aceptar datos nulos, debe aplicarlos.

La elección de la excepción podría ser mejor. Por lo general, voy con un IllegalArgumentException.

Si es la brevedad del método lo que le molesta, tengo que decir que estoy de acuerdo. No hay información nueva allí.

+0

No creo que 'IllegalArgumentException' sea una mejor opción. 'NPE' es más específico. También puede consultar el ítem 60 de Java Efectivo al respecto. –

+0

Lo echaré un vistazo, pero no sé si estoy de acuerdo. El mensaje en IAE puede dejarlo bastante claro. También puede marcar otras condiciones (por ejemplo, Cadena que no puede ser ni nula ni nula). Su interpretación es muy estrecha, pero correcta para este problema. – duffymo

0

Creo que hacer este tipo de comprobaciones tiene sentido si un método hace un procesamiento que lleva mucho tiempo o es difícil de deshacer antes de que realmente active el NPE. En el ejemplo dado, no creo que tenga sentido.

Por otro lado: usar assert o lanzar una excepción más específica como IllegalArgumentException podría tener más sentido.

0

En C# existe una ArgumentNullException. Esta excepción toma el nombre del argumento en el constructor. Entonces la persona que llama pudo ver, que argumento tal vez es ilicidad NULL. IllegalArgumentException es casi equivalente a Java.

2

La situación que describe puede ser útil en uno de los siguientes supuestos:

1.) Si tiene que realizar algunas operaciones que son o bien costosos o hacen cambiar un estado mundial antes de la ejecución someObject.aMethodCall() se puede prevenir código de restitución y pérdida de ciclos de ejecución.

2.) Si someObject se almacena dentro de una estructura de datos, puede crear una posible trampa si en algún momento posterior los datos se recuperan de la estructura de datos. Creo que recuerdo algunas clases en el marco de recopilación de Java, que arrojan más bien un NPE que permitir un nulo en la estructura de almacenamiento.

+0

Un ejemplo de las colecciones de Java: las versiones anteriores de un 'TreeSet' vacío permitían agregar' null', solo para lanzar un NPE cuando se agregaba un segundo elemento. La versión actual de 'TreeSet.add' verifica explícitamente' null'. –

6

Hay una caja de esquina donde algo así tendría sentido. Si no usa algún Objeto, el cortocircuito inmediato del caso de error al inicio de la función puede ser útil.

public void someMethod(Object someObject){ 

    if(someObject == null) throw new NullPointerException(); 

    expensiveOperationNotUsingSomeObject(); 

    someObject.aMethodCall(); 
} 
+1

+1 un cheque y tiro explícito * puede * ser útil. Piensa fallar rápido, falla temprano. – Qwerky

2

personalmente la razón por la que nunca había echo una NullPointerException como parte de un método de API pública es porque hace que sea mucho más difícil para el programador de distinguir entre un error de programación de su lado y un error en mi código (es decir, ¿dejé deliberadamente lanzar o no la NPE?).

Lanzar una excepción diferente hace que la intención sea mucho más clara y también ayuda al programador a descubrir más fácilmente lo que está mal. Así que iría con IllegalArgumentException allí.

Si se trata de un método interno? Usaría aserciones o simplemente dejaría que se bloquee. No tiene sentido lanzar explícitamente un imo NPE.

Cuestiones relacionadas