Puedo ver eso @Nullable
y las @Nonnull
anotaciones pueden ser útiles para prevenir NullPointerException
s pero no se propagan muy lejos.
- La efectividad de estas anotaciones disminuye completamente después de un nivel de indirección, por lo que si solo agrega unas pocas, no se propagan muy lejos.
- Dado que estas anotaciones no se aplican correctamente, existe el peligro de asumir que un valor marcado con
@Nonnull
no es nulo y, en consecuencia, no realiza comprobaciones nulas.
El siguiente código hace que un parámetro marcado con @Nonnull
sea null
sin generar ninguna queja. Lanza un NullPointerException
cuando se ejecuta.
public class Clazz {
public static void main(String[] args){
Clazz clazz = new Clazz();
// this line raises a complaint with the IDE (IntelliJ 11)
clazz.directPathToA(null);
// this line does not
clazz.indirectPathToA(null);
}
public void indirectPathToA(Integer y){
directPathToA(y);
}
public void directPathToA(@Nonnull Integer x){
x.toString(); // do stuff to x
}
}
¿Hay alguna manera de hacer que estas anotaciones se apliquen más estrictamente y / o se propaguen más?
java
annotations
nullpointerexception
nullable
code-standards
Mike Rylander
fuente
fuente
@Nullable
o@Nonnull
, pero si valen la pena, es muy "probable que soliciten debate"@Nonnull
al llamar a un@Nonnull
método con una variable anulable. Por supuesto, la conversión con una anotación no es posible en Java 7, pero Java 8 agregará la capacidad de aplicar anotaciones al uso de una variable, incluidas las conversiones. Entonces, esto puede ser posible implementar en Java 8.(@NonNull Integer) y
es sintácticamente posible, pero un compilador no puede emitir ningún código de byte específico basado en la anotación. Para las afirmaciones de tiempo de ejecución, los métodos auxiliares pequeños son suficientes como se discutió en bugs.eclipse.org/442103 (por ejemplo,directPathToA(assertNonNull(y))
), pero ten en cuenta que esto solo ayuda a fallar rápidamente. La única forma segura es realizar una comprobación nula real (más, con suerte, una implementación alternativa en la rama else).@Nonnull
y de@Nullable
qué está hablando, ya que hay múltiples molestias similares (consulte esta pregunta ). ¿Estás hablando de las anotaciones en el paquetejavax.annotation
?Respuestas:
Respuesta corta: supongo que estas anotaciones solo son útiles para que su IDE le advierta de posibles errores de puntero nulo.
Como se dice en el libro "Código limpio", debe verificar los parámetros de su método público y también evitar los invariantes.
Otro buen consejo es que nunca devuelve valores nulos, sino que usa el Patrón de objetos nulos .
fuente
Optional
tipo en lugar de simplenull
Optional
y anulable en este caso es queOptional
comunica mejor que este valor puede estar vacío intencionalmente. Ciertamente, no es una varita mágica y en el tiempo de ejecución puede fallar exactamente de la misma manera que la variable anulable. Sin embargo, la recepción API por programador es mejorOptional
en mi opinión.Además de su IDE que le da pistas cuando pasa
null
a métodos que esperan que el argumento no sea nulo, existen otras ventajas:Esto puede ayudar a que su código sea más fácil de mantener (ya que no necesita
null
verificaciones) y menos propenso a errores.fuente
assert
. Encuentro@Nullable
y@Nonnull
para ser útiles ideas, pero me gustaría más fuerza detrás de ellos, en lugar de nosotros hipótesis acerca de lo que uno puede hacer con ellos, que todavía deja abierta la posibilidad de no hacer nada con ellos.Creo que esta pregunta original apunta indirectamente a una recomendación general de que todavía se necesita la verificación de puntero nulo en tiempo de ejecución, aunque se use @NonNull. Consulte el siguiente enlace:
Nuevas anotaciones de tipo de Java 8
En el blog anterior, se recomienda que:
fuente
Compilando el ejemplo original en Eclipse en el cumplimiento 1.8 y con el análisis nulo basado en anotaciones habilitado, obtenemos esta advertencia:
Esta advertencia está redactada de forma análoga a las advertencias que se obtienen al mezclar código genérico con código heredado utilizando tipos sin formato ("conversión no verificada"). Tenemos exactamente la misma situación aquí: el método
indirectPathToA()
tiene una firma "heredada" en el sentido de que no especifica ningún contrato nulo. Las herramientas pueden informar fácilmente de esto, por lo que lo perseguirán por todos los callejones donde las anotaciones nulas deben propagarse pero aún no lo son.Y cuando usas un inteligente
@NonNullByDefault
, ni siquiera tenemos que decir esto cada vez.En otras palabras: si las anotaciones nulas "se propagan muy lejos" pueden depender de la herramienta que use y de cuán rigurosamente preste atención a todas las advertencias emitidas por la herramienta. Con las anotaciones nulas TYPE_USE , finalmente tiene la opción de dejar que la herramienta le advierta sobre cada NPE posible en su programa, porque la nulidad se ha convertido en una propiedad intrínseca del sistema de tipos.
fuente
Estoy de acuerdo en que las anotaciones "no se propagan muy lejos". Sin embargo, veo el error del lado del programador.
Entiendo la
Nonnull
anotación como documentación. El siguiente método expresa que se requiere (como condición previa) un argumento no nulox
.El siguiente fragmento de código contiene un error. El método llama
directPathToA()
sin exigir quey
no sea nulo (es decir, no garantiza la condición previa del método llamado). Una posibilidad es agregar unaNonnull
anotación también aindirectPathToA()
(propagar la condición previa). La posibilidad dos es verificar la nulidad dey
inindirectPathToA()
y evitar la llamada adirectPathToA()
cuandoy
es nulo.fuente
@Nonnull
que tienenindirectPathToA(@Nonnull Integer y)
es mi humilde opinión, una mala práctica: tendrá que mainain la propagación de la pila de llamadas completa (por lo que si se añade unnull
cheque endirectPathToA()
, tendrá que sustituir@Nonnull
por@Nullable
en la pila de llamadas completa). Esto sería un gran esfuerzo de mantenimiento para grandes aplicaciones.Lo que hago en mis proyectos es activar la siguiente opción en la inspección del código "Condiciones constantes y excepciones":
Sugerir anotación @Nullable para métodos que posiblemente puedan devolver valores nulos e informar valores anulables pasados a parámetros no anotados
Cuando se activa, todos los parámetros no anotados se tratarán como no nulos y, por lo tanto, también verá una advertencia en su llamada indirecta:
Para verificaciones aún más fuertes, el Checker Framework puede ser una buena opción (vea este buen tutorial .
Nota : aún no lo he usado y puede haber problemas con el compilador Jack: vea este informe de errores
fuente
En Java, usaría el tipo Opcional de Guava . Al ser un tipo real, obtienes garantías de compilación sobre su uso. Es fácil omitirlo y obtener un
NullPointerException
, pero al menos la firma del método comunica claramente lo que espera como argumento o lo que podría devolver.fuente
java.util.Optional
lugar de la clase Guava. Vea las notas / comparación de Guava para detalles sobre las diferencias.Si usa Kotlin, admite estas anotaciones de nulabilidad en su compilador y evitará que pase un método nulo a un método java que requiere un argumento no nulo. Aunque esta pregunta originalmente estaba dirigida a Java, menciono esta característica de Kotlin porque está específicamente dirigida a estas anotaciones de Java y la pregunta era "¿Hay alguna manera de hacer que estas anotaciones se apliquen más estrictamente y / o se propaguen más?" y esta característica hace que estas anotaciones se apliquen más estrictamente .
Clase Java usando
@NotNull
anotacionesClase Kotlin llamando a la clase Java y pasando nulo para el argumento anotado con @NotNull
Error del compilador de Kotlin al aplicar la
@NotNull
anotación.ver: http://kotlinlang.org/docs/reference/java-interop.html#nullability-annotations
fuente
myString.hashCode()
seguirá arrojando NPE incluso si@NotNull
no se agrega en el parámetro. Entonces, ¿qué es más específico acerca de agregarlo?Dado que la nueva característica de Java 8 Opcional ya no debe usar @Nullable o @Notnull en su propio código . Tome el siguiente ejemplo:
Podría reescribirse con:
El uso de una opción te obliga a comprobar el valor nulo . En el código anterior, solo puede acceder al valor llamando al
get
método.Otra ventaja es que el código se vuelve más legible . Con la adición de Java 9 ifPresentOrElse , la función podría incluso escribirse como:
fuente
Optional
, todavía hay muchas bibliotecas y marcos que usan estas anotaciones, de modo que no es factible actualizar / reemplazar todas sus dependencias con versiones actualizadas para usar Opcionales.Optional
Sin embargo, puede ayudar en situaciones en las que utilice nulo dentro de su propio código.