¿Cuál es la mejor manera de saber si todas las variables en una clase son nulas?

5 minutos de lectura

avatar de usuario de th3an0maly
th3an0maly

Esto significaría que la clase se inicializó, pero las variables no se establecieron.

Una clase de muestra:

public class User {

    String id = null;
    String name = null;

    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

La clase real es enorme que prefiero no comprobar. if(xyz == null) para cada una de las variables.

  • if(id == null) es el mejor método.

    – KV Prajapati

    11 de septiembre de 2012 a las 3:13


  • Los campos de referencia se inicializan a su valor predeterminado, nullen ausencia de un inicializador explícito.

    – obataku

    11 de septiembre de 2012 a las 3:21

Avatar de usuario de Didier L
didier l

Otra solución no reflectante para Java 8, en la línea de la respuesta de paxdiabo pero sin usar una serie de if‘s, sería transmitir todos los campos y verificar la nulidad:

return Stream.of(id, name)
        .allMatch(Objects::isNull);

Esto sigue siendo bastante fácil de mantener mientras evita la reflexión. martillo.

  • ¿Hay alguna forma de obtener los valores de campo, por ejemplo: Stream.of (id, nombre), eliminar campos nulos y devolver la lista de valores de campos no nulos?

    – Enjuague S

    3 de marzo de 2018 a las 13:31

  • @Rinsen puedes usar filter() pero esa es una pregunta diferente y es probable que ya se haya hecho en SO.

    – Didier L.

    3 de marzo de 2018 a las 13:39

  • gracias por el comentario, esa es una pregunta diferente, pero ¿puede decirme cómo hacerlo ya que tengo un problema y no puedo encontrar una solución eficiente? Gracias de antemano

    – Enjuague S

    3 de marzo de 2018 a las 14:32

avatar de usuario de arshajii
arshajii

Prueba algo como esto:

public boolean checkNull() throws IllegalAccessException {
    for (Field f : getClass().getDeclaredFields())
        if (f.get(this) != null)
            return false;
    return true;            
}

Aunque probablemente sería mejor verificar cada variable si es factible.

  • En cuanto al rendimiento, ¿está tan por detrás del if(variable==null) ¿método?

    – th3an0maly

    12 de septiembre de 2012 a las 10:07

  • Sí, es probable que tome mucho más tiempo que if (var == null).

    – arshajii

    12/09/2012 a las 11:00

  • @Yar, para que esto funcione para campos privados, debe hacer f.setAccessible(true)

    – Jawa

    22/03/2018 a las 18:30


  • el uso de la reflexión es bastante lento, oculta mucho de lo que realmente se hace y, en un pensamiento más general, puede ser una molestia refactorizar (un campo puede marcarse como no utilizado por su IDE cuando en realidad es a través de la reflexión: / y lo hará nunca se sabe que realmente se usó a menos que tenga buenas pruebas o ejecute su aplicación) Por supuesto, esto no prohíbe usar la reflexión, pero si puede usar cualquier otra opción … hágalo

    – minioim

    8 de agosto de 2019 a las 13:03


  • Nunca será demasiado decir que necesita agregar f.setAccessible(true) para evitar IllegalAccessException en campos privados.

    – Ara Kokeba

    21 de noviembre de 2019 a las 20:03


Avatar de usuario de Martin Tarjányi
Martín Tarjányi

Esto se puede hacer con bastante facilidad utilizando un Lombok generado equals y una estática EMPTY objeto:

import lombok.Data;

public class EmptyCheck {
    public static void main(String[] args) {
        User user1 = new User();

        User user2 = new User();
        user2.setName("name");

        System.out.println(user1.isEmpty()); // prints true
        System.out.println(user2.isEmpty()); // prints false
    }

    @Data
    public static class User {
        private static final User EMPTY = new User();

        private String id;
        private String name;
        private int age;

        public boolean isEmpty() {
            return this.equals(EMPTY);
        }
    }
}

requisitos previos:

  • El constructor predeterminado no debe implementarse con un comportamiento personalizado, ya que se usa para crear el EMPTY objeto
  • Todos los campos de la clase deben tener un implementado equals (Los tipos de Java incorporados generalmente no son un problema, en el caso de tipos personalizados, puede usar Lombok)

Ventajas:

  • No hay reflexión involucrada
  • Como se agregaron nuevos campos a la clase, esto no requiere ningún mantenimiento ya que debido a Lombok, se verificarán automáticamente en el equals implementación
  • A diferencia de otras respuestas, esto funciona no solo para comprobaciones nulas, sino también para tipos primitivos que tienen un valor predeterminado no nulo (por ejemplo, si el campo es int lo comprueba 0en caso de boolean por falseetc.)

  • Esto creará un objeto extra. EMPTY junto con cada objeto. ¿Afectará esto al rendimiento?

    – Sp4RX

    5 de marzo de 2019 a las 0:34

  • Vacío es un campo estático aquí, por lo que no debería ser un problema.

    – Martín Tarjányi

    25 de julio de 2019 a las 17:13

  • @MartinTarjányi pero el método equals() en java compara instancias y no sus valores de campo. Deberá anular equals() y hashCode().

    – Tamim Attafi

    15 de enero de 2020 a las 6:09

  • por eso usé la anotación lombok

    – Martín Tarjányi

    15 de enero de 2020 a las 6:10

Si quieres esto para pruebas unitarias, solo uso el hasNoNullFieldsOrProperties() método de assertj

assertThat(myObj).hasNoNullFieldsOrProperties();

¿Qué hay de las corrientes?

public boolean checkFieldsIsNull(Object instance, List<String> fieldNames) {

    return fieldNames.stream().allMatch(field -> {
        try {
            return Objects.isNull(instance.getClass().getDeclaredField(field).get(instance));
        } catch (IllegalAccessException | NoSuchFieldException e) {
            return true;//You can throw RuntimeException if need.
        }
    });
}

  • esto no es escalable.

    – saran3h

    30 oct 2021 a las 6:15

avatar de usuario de paxdiablo
paxdiablo

“Mejor” es un término tan subjetivo 🙂

Simplemente usaría el método de verificar cada variable individual. Si su clase ya tiene muchos de estos, el aumentar en tamaño no va a ser tanto si haces algo como:

public Boolean anyUnset() {
    if (  id == null) return true;
    if (name == null) return true;
    return false;
}

Siempre que mantenga todo en el mismo orden, los cambios de código (y la verificación automática con un script si está paranoico) serán relativamente sencillos.

Alternativamente (asumiendo que son todas cadenas), básicamente podría poner estos valores en un mapa de algún tipo (por ejemplo, HashMap) y solo mantenga una lista de los nombres clave para esa lista. De esa manera, podría iterar a través de la lista de claves, verificando que los valores estén configurados correctamente.

  • esto no es escalable.

    – saran3h

    30 oct 2021 a las 6:15

Creo que esta es una solución que resuelve su problema fácilmente: (devuelve verdadero si alguno de los parámetros no es nulo)

  public boolean isUserEmpty(){ 
boolean isEmpty;
isEmpty =  isEmpty = Stream.of(id,
            name)
        .anyMatch(userParameter -> userParameter != null);

return isEmpty;}

Otra solución para la misma tarea es: (puede cambiarlo a if (isEmpty==0) comprueba si todos los parámetros son nulos.

public boolean isUserEmpty(){  
       long isEmpty;
            isEmpty = Stream.of(id,
                    name)
                    .filter(userParameter -> userParameter != null).count();
    
          return  isEmpty > 0

    }

¿Ha sido útil esta solución?