È possibile in Java per verificare se gli oggetti campi sono null e quindi aggiungere valore predefinito per tutti gli attributi?

StackOverflow https://stackoverflow.com/questions/2146129

  •  23-09-2019
  •  | 
  •  

Domanda

Ho bisogno di assicurarsi che nessun attributo dell'oggetto è null e aggiungere valore di default nel caso in cui se il valore è null.C'è un modo semplice per fare questo, o devo farlo manualmente controllando ogni attributo dal suo getter e setter?

È stato utile?

Soluzione

È possibile utilizzare la reflection per iterare campo dell'oggetto, e impostarle. Si potrebbe, ovviamente, bisogno di una sorta di mappatura tra i tipi o addirittura i nomi dei campi ei valori predefiniti richiesti, ma questo può essere fatto facilmente in un ciclo. Ad esempio:

for (Field f : obj.getClass().getFields()) {
  f.setAccessible(true);
  if (f.get(obj) == null) {
     f.set(obj, getDefaultValueForType(f.getType()));
  }
}

[Aggiornamento]

Con Java moderna, è possibile utilizzare le annotazioni per impostare i valori predefiniti per i campi su una base per ogni classe. Una completa implementazione potrebbe essere simile a questo:

// DefaultString.java:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface DefaultString {
    String value();
}

// DefaultInteger.java:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface DefaultInteger {
    int value();
}

// DefaultPojo.java:
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

public class DefaultPojo {

    public void setDefaults() {
        for (Field f : getClass().getFields()) {
            f.setAccessible(true);
            try {
                if (f.get(this) == null) {
                    f.set(this, getDefaultValueFromAnnotation(f.getAnnotations()));
                }
            } catch (IllegalAccessException e) { // shouldn't happen because I used setAccessible
            }
        }
    }

    private Object getDefaultValueFromAnnotation(Annotation[] annotations) {
        for (Annotation a : annotations) {
            if (a instanceof DefaultString)
                return ((DefaultString)a).value();
            if (a instanceof DefaultInteger)
                return ((DefaultInteger)a).value();
        }
        return null;
    }

}

// Test Pojo
public class TestPojo extends DefaultPojo {
    @DefaultString("Hello world!")
    public String stringValue;
    @DefaultInteger(42);
    public int integerValue;
}

Poi i valori predefiniti per una TestPojo possono essere impostati semplicemente eseguendo test.setDetaults()

Altri suggerimenti

È necessario filtrare manualmente input per costruttori e setter. Beh ... si potrebbe usare riflessione, ma non vi consiglio di esso. Parte del lavoro di costruttori e setter è per convalidare l'input. Questo può includere le cose come:

public void setPrice(double price) {
  if (price < 0.0d) {
    throw new IllegalArgumentException("price cannot be negative " + price);
  }
  this.price = price;
}

e

public void setName(String name) {
  if (name == null) {
    throw new NullPointerException("name cannot be null");
  }
  this.name = name;
}

Si potrebbe utilizzare funzioni wrapper per il controllo effettivo e gettando l'eccezione.

Hibernate Validator 4.0 , l'implementazione di riferimento della JSR 303: Bean Validation .

Questo è un esempio di una classe annotata:

public class Address {

    @NotNull 
    private String line1;
    private String line2;
    private String zip;
    private String state;

    @Length(max = 20)
    @NotNull
    private String country;

    @Range(min = -2, max = 50, message = "Floor out of range")
    public int floor;

        ...
}

Per un'introduzione, vedere Introduzione a JSR 303 (Bean Validation) - parte 1 e la parte 2 o 'la sezione Operazioni preliminari' della guida di riferimento che è parte della distribuzione di Hibernate Validator.

Soluzione non riflettente per Java 8, senza l'utilizzo di una serie di se di, sarebbero per lo streaming di tutti i campi e verificare la presenza di nullness:

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

Questa rimane abbastanza facile da mantenere, evitando il martello riflesso. Ciò restituirà vero per gli attributi nulli.

È possibile creare una funzione che restituisce un valore booleano e controlla tutti gli attributi. È possibile chiamare quella funzione per fare il lavoro per voi.

In alternativa, è possibile inizializzare l'oggetto con valori di default. In questo modo non c'è bisogno per voi di fare alcun controllo.

Non ho abbastanza contesto per darvi una risposta corretta, ma io suggerisco di farvi codice immutabile il più possibile. Utilizzare i campi public final. Niente più getters o setters: ogni campo deve essere definito dal constructor. Il tuo codice è più breve, più leggibile e ti impedisce di scrivere codice con effetti collaterali.

Non vi impedisce di passare gli argomenti nulli al costruttore però ... È ancora possibile controllare ogni argomento come suggerito da @ Cletus, ma io vi suggerisco di buttare IllegalArgumentException invece di NullPointerException che non riconoscono alcuna nuovo suggerimento su quello che hai fatto.

Comunque, questo è quello che faccio quanto posso e ha migliorato il mio codice (leggibilità, stabilità) ad un grande estendere. Tutti nella mia squadra lo fa e siamo molto soddisfatti. Abbiamo imparato che quando cerchiamo di scrivere del codice erlang dove tutto è immutabile.

Spero che questo aiuti.

Ho provato questo e funziona senza problemi per verificare se il campo è vuoto.Ho risposto alla tua domanda parzialmente in quanto non ho provato personalmente per aggiungere i valori di default per gli attributi

if(field.getText()!= null && !field.getText().isEmpty())

Speranza che aiuta

Questo non è quello di verificare la presenza di nulla, invece questo sarà utile per la conversione di un oggetto esistente a un oggetto vuoto (oggetto fresca). Non so se questo è rilevante o no, ma ho avuto un tale requisito.

@SuppressWarnings({ "unchecked" })
static void emptyObject(Object obj) 
{
    Class c1 = obj.getClass();
    Field[] fields = c1.getDeclaredFields();

    for(Field field : fields)
    {
        try
        {
            if(field.getType().getCanonicalName() == "boolean")
            {
                field.set(obj, false);
            }
            else if(field.getType().getCanonicalName() == "char")
            {
                field.set(obj, '\u0000');
            }
            else if((field.getType().isPrimitive()))
            {
                field.set(obj, 0);
            }
            else
            {
                field.set(obj, null);
            }
        }
        catch(Exception ex)
        {

        }
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top