Muchas veces me encuentro con una comprobación nula cuando obtengo un valor de alguna jerarquía de datos para evitar NullPointerExceptions, que encuentro propenso a errores y necesita mucha repetitiva.
He escrito una rutina muy simple que me permite omitir la comprobación nula al buscar un objeto ...
public final class NoNPE {
public static <T> T get(NoNPEInterface<T> in) {
try {
return in.get();
} catch (NullPointerException e) {
return null;
}
}
public interface NoNPEInterface<T> {
T get();
}
}
Lo uso un poco así ...
Room room = NoNPE.get(() -> country.getTown().getHouses().get(0).getLivingRoom());
Lo anterior resulta en que obtengo un objeto Room o un valor nulo, sin tener que anular todos los niveles principales.
¿Qué opinas de lo anterior? ¿Estoy creando un patrón problemático? ¿Hay una mejor manera de hacer esto en tu opinión?
java.util.Optional
lugar de valores nulos para representar datos faltantes? Esto proporciona utilidades útiles tanto para el caso que describe como para los casos en que desea continuar con los datos predeterminados en lugar de simplemente devolver una condición de falla al final de la cadena ...Option
(oMaybe
) mónada :)Respuestas:
Tu solución es muy inteligente. El problema que veo es el hecho de que usted no sabe por qué recibió una
null
? ¿Fue porque la casa no tenía habitaciones? ¿Fue porque el pueblo no tenía casas? ¿Fue porque el país no tenía ciudades? ¿Fue porque hubo unnull
en la posición 0 de la colección debido a un error incluso cuando hay casas en las posiciones 1 y superiores?Si hace un uso extensivo de la
NonPE
clase, tendrá serios problemas de depuración. Creo que es mejor saber exactamente dónde se rompe la cadena que obtener silenciosamente algonull
que podría estar ocultando un error más profundo.También esto viola la Ley de Demeter :
country.getTown().getHouses().get(0).getLivingRoom()
. La mayoría de las veces, violar algún buen principio hace que tenga que implementar soluciones poco ortodoxas para resolver el problema causado por la violación de dicho principio.Mi recomendación es que lo use con precaución e intente resolver la falla de diseño que le obliga a incurrir en el antipatrón de choque de trenes (para que no tenga que usarlo en
NonPE
todas partes). De lo contrario, puede tener errores que serán difíciles de detectar.fuente
Option
mónada, no le importa en qué parte de la cadena se encuentre el valor ausente. Cuando te preocupes por eso, probablemente usarías un tipo diferente, comoEither
.?.
y los?[]
operadores. Un ejemplo de cuándo podría querer usar tal cosa es la configuración jerárquica del lado del servidor.var shouldDoThing = settings?.a?.b?.c ?? defaultSetting;
¿A quién le importa por qué alguna parte de eso fue nula? Tal vez no pudiste obtener la configuración. Tal vez decidió eliminar una sección de la configuración. En cualquier caso, nunca puede contar con obtener la configuración del servidor, por lo que una opción predeterminada suele ser una buena idea, y es poco probable que le importe por qué no pudo obtener la configuración real a menos que ocurra con mucha frecuencia cuando no debería .settings.a.b.c
. Por otra parte, este es un solo ejemplo aislado.La idea está bien, de hecho muy buena. Dado que Java 8
Optional
existen los tipos, se puede encontrar una explicación detallada en el tipo Java Opcional . Un ejemplo con lo que publicaste esY más adelante.
fuente
Optional
es la solución más legible de las dos, aunque solo sea porque, a diferencia de su propuesta, es un idioma muy común . ¡Es aún más conciso que el tuyo!Su método funciona lo suficientemente bien para su propósito previsto, aunque devuelve
null
s cuando obtiene unNullPointerException
sonido como un mal diseño.Intente evitar
null
s cuando pueda y solo páselos cuando representen algo o tengan un significado especial y solo devuélvalos cuando representen / signifiquen algo; de lo contrario, debe lanzar aNullPointerException
. Esto evita errores y confusión. Si unObject
no debería sernull
, unNullPointer
debería ser arrojado. Si un objeto puede ser,null
entonces nada saldrá mal cuando se pasa uno. De lo contrario, su método anterior funciona.fuente
Puedo sentir tu dolor, pero la solución propuesta es una mala idea.
NoNPE.get
.Optional.map
es lo que estás buscando.Como nota al margen,
NoNPEInterface
es un duplicado dejava.util.function.Supplier
.En algunos casos, podría considerar usar una utilidad de evaluación de expresiones que esté presente en muchos marcos (por ejemplo: EL, SpEL):
fuente