java - desde - insertar datos de netbeans a oracle
¿Cómo evitar la comprobación de valores nulos en el encadenamiento de métodos? (6)
Esta pregunta ya tiene una respuesta aquí:
- Cadena de verificación nula frente a la captura de NullPointerException 19 respuestas
- Evitando! = Declaraciones nulas 60 respuestas
Necesito comprobar si algún valor es nulo o no. Y si no es nulo, simplemente establece algunas variables en verdadero. No hay ninguna otra declaración aquí. Recibí demasiadas verificaciones de estado como esta.
¿Hay alguna manera de manejar estas comprobaciones nulas sin verificar todos los valores de retorno del método?
if(country != null && country.getCity() != null && country.getCity().getSchool() != null && country.getCity().getSchool().getStudent() != null .....) {
isValid = true;
}
Pensé verificar directamente la variable e ignorar NullpointerException. ¿Es esta una buena practica?
try{
if(country.getCity().getSchool().getStudent().getInfo().... != null)
} catch(NullPointerException ex){
//dont do anything.
}
Como alternativa a otro buen uso de Optional
, también podríamos usar un método de utilidad con un parámetro Var-args de Supplier<Object>
.
Tiene sentido ya que no tenemos muchos niveles anidados en el objeto para verificar, sino muchos campos para verificar.
Además, puede modificarse fácilmente para registrar / manejar algo cuando se detecta un null
.
boolean isValid = isValid(() -> address, // first level
() -> address.getCity(), // second level
() -> address.getCountry(),// second level
() -> address.getStreet(), // second level
() -> address.getZip(), // second level
() -> address.getCountry() // third level
.getISO()
@SafeVarargs
public static boolean isValid(Supplier<Object>... suppliers) {
for (Supplier<Object> supplier : suppliers) {
if (Objects.isNull(supplier.get())) {
// log, handle specific thing if required
return false;
}
}
return true;
}
Supongamos que desea agregar algunos rastros, podría escribir:
boolean isValid = isValid( Arrays.asList("address", "city", "country",
"street", "zip", "Country ISO"),
() -> address, // first level
() -> address.getCity(), // second level
() -> address.getCountry(),// second level
() -> address.getStreet(), // second level
() -> address.getZip(), // second level
() -> address.getCountry() // third level
.getISO()
);
@SafeVarargs
public static boolean isValid(List<String> fieldNames, Supplier<Object>... suppliers) {
if (fieldNames.size() != suppliers.length){
throw new IllegalArgumentException("...");
}
for (int i = 0; i < suppliers.length; i++) {
if (Objects.isNull(suppliers.get(i).get())) {
LOGGER.info( fieldNames.get(i) + " is null");
return false;
}
}
return true;
}
El enfoque orientado a objetos es poner el método isValid en Country y en las otras clases. No reduce la cantidad de chequeos nulos, pero cada método solo tiene uno y no los repites.
public boolean isValid() {
return city != null && city.isValid();
}
Esto supone que la validación es la misma en todos los lugares donde se usa su país, pero normalmente ese es el caso. De lo contrario, el método debe llamarse hasStudent (), pero esto es menos general y usted corre el riesgo de duplicar toda la interfaz de la escuela en el país. Por ejemplo, en otro lugar puede necesitar hasTeacher () o hasCourse ().
Otro enfoque es usar objetos nulos:
public class Country {
public static final Country NO_COUNTRY = new Country();
private City city = City.NO_CITY;
// etc.
}
No estoy seguro de que sea preferible este caso (estrictamente necesitaría una subclase para anular todos los métodos de modificación), el modo Java 8 sería ir con Opcional como método en las otras respuestas, pero sugeriría abrazarlo más plenamente:
private Optional<City> city = Optional.ofNullable(city);
public Optional<City> getCity() {
return city;
}
Tanto para objetos nulos como Nullable solo funcionan si siempre los usa en lugar de nulos (observe la inicialización del campo), de lo contrario, todavía necesita las comprobaciones nulas. Entonces esta opción evita el nulo, pero su código se vuelve más detallado para las comprobaciones nulas reducidas en otros lugares.
Por supuesto, el diseño correcto puede ser usar Colecciones siempre que sea posible (en lugar de Opcional). Un País tiene un conjunto de Ciudad, Ciudad tiene un conjunto de Escuelas, que tiene un conjunto de estudiantes, etc.
Java no tiene operaciones "nulamente seguras", como, por ejemplo, la seguridad nula de Kotlin
Tu también puedes:
- coger el NPE e ignorarlo
- verifica todas las referencias manualmente
- usar Opcional según las otras respuestas
- use algún tipo de herramienta como XLST
De lo contrario, si tiene control sobre los objetos de dominio, puede rediseñar sus clases para que la información que necesita esté disponible desde el objeto de nivel superior (haga que la clase Country
haga toda la verificación nula ...)
No, generalmente no es una buena práctica en Java capturar un NPE en lugar de verificar nulamente sus referencias.
Puede usar Optional
para este tipo de cosas si lo prefiere:
if (Optional.ofNullable(country)
.map(Country::getCity)
.map(City::getSchool)
.map(School::getStudent)
.isPresent()) {
isValid = true;
}
o simplemente
boolean isValid = Optional.ofNullable(country)
.map(Country::getCity)
.map(City::getSchool)
.map(School::getStudent)
.isPresent();
Puede usar Optional
aquí, pero crea un objeto opcional en cada paso.
boolean isValid = Optional.ofNullable(country)
.map(country -> country.getCity()) //Or use method reference Country::getCity
.map(city -> city.getSchool())
.map(school -> school.getStudent())
.map(student -> true)
.orElse(false);
//OR
boolean isValid = Optional.ofNullable(country)
.map(..)
....
.isPresent();
También puede consultar la Opción de Vavr, que como se describe en las publicaciones siguientes es mejor que la Opción de Java y tiene una API mucho más rica.