Ist es möglich, in Java zu überprüfen, ob Objekte Felder null sind und fügen Sie dann Standardwert für alle diese Attribute?

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

  •  23-09-2019
  •  | 
  •  

Frage

Ich muss sicherstellen, dass kein Objekt Attribut null ist und den Standardwert für den Fall hinzufügen, wenn es null ist. Gibt es eine einfache Möglichkeit, dies zu tun, oder muss ich es durch Überprüfung jedes Attribut durch seine Getter und Setter manuell tun?

War es hilfreich?

Lösung

Sie können Reflexion Iterierte verwenden, um über das entsprechende Feld Objekt und stellen sie. Sie würden offensichtlich eine Art von Zuordnung zwischen Typen oder sogar Feldnamen müssen und die erforderlichen Standardwerten, aber dies kann in einer Schleife ganz einfach durchgeführt werden. Zum Beispiel:

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

[Update]

Mit modernen Java können Sie Anmerkungen verwenden, um die Standardwerte für die Felder auf einer pro Klasse Basis einzustellen. Eine vollständige Implementierung könnte wie folgt aussehen:

// 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;
}

Dann Standardwerte für ein TestPojo können durch Ausführen test.setDetaults() nur eingestellt werden,

Andere Tipps

Sie müssen Filtereingang an Konstrukteure und Setter manuell. Nun ... Sie könnten Reflexion verwenden, aber ich würde es nicht empfehlen. Ein Teil der Arbeit der Konstrukteure und Setter eingegeben zu validieren. Das kann auch Dinge wie:

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

und

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

Sie können Wrapper-Funktionen für die eigentliche Prüfung nutzen und die Ausnahme zu werfen.

Vielleicht überprüfen Hibernate Validator 4.0 , die Referenzimplementierung der JSR 303: Bean Validation .

Dies ist ein Beispiel eines kommentierten Klasse:

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;

        ...
}

Eine Einführung finden Sie unter mit Erste Schritte 303 JSR (Bean Validation) - Teil 1 und Teil 2 oder die‚Erste Schritte‘des Referenzhandbuch, das Teil der Hibernate Validator Verteilung ist.

Nicht reflektierendes Lösung für Java 8, ohne eine Reihe von, wenn die Verwendung wäre es, alle Felder zu streamen und prüfen, ob nullness:

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

Das bleibt ganz einfach zu halten, während die Reflexion Hammer zu vermeiden. Dies wird return true für null Attribute.

Sie können eine Funktion erstellen, die jedes Attribut einen Booleschen Wert und überprüft, zurückgibt. Sie können diese Funktion aufrufen, die Arbeit für Sie tun.

Alternativ können Sie das Objekt mit Standardwerten initialisieren. Auf diese Weise gibt es keine Notwendigkeit für Sie jede Kontrolle zu tun.

Ich habe nicht genug Kontext Ihnen eine richtige Antwort zu geben, aber ich werde vorschlagen, dass Sie Ihnen Code machen unveränderlich , so viel wie möglich. Verwenden public final Felder aus. Nicht mehr getters oder setters: hat jedes Feld durch die constructor definiert werden. Ihr Code ist kürzer, besser lesbar und verhindert, dass Sie Code mit Nebenwirkungen zu schreiben.

Es hindert Sie nicht von null Argumente zu Ihrem Konstruktor aber ... Sie können immer noch jedes Argument prüfen, wie durch @cletus vorgeschlagen, aber ich werde Ihnen vorschlagen IllegalArgumentException statt NullPointerException zu werfen, die nicht nicht nicht geben neuer Hinweis über das, was du getan hast.

Wie auch immer, das ist, was ich tun, so viel wie ich kann, und es verbessert meinen Code (Lesbarkeit, Stabilität) zu einem großen verlängern. Jeder in meinem Team tut so, und wir sind sehr zufrieden. Wir haben gelernt, dass, wenn wir versuchen, einige erlang Code zu schreiben, wo alles unveränderlich ist.

Hope, das hilft.

Ich habe versucht und es funktioniert ohne Probleme zu validieren, wenn das Feld leer ist. Ich habe Ihre Frage teilweise beantwortet, wie ich es nicht persönlich versucht, die Standardwerte zu Attribute

hinzufügen
if(field.getText()!= null && !field.getText().isEmpty())

Hope es hilft

Dies ist nicht für null zu überprüfen, wird stattdessen diese hilfreich sein, ein bestehendes Objekt in ein leeres Objekt bei der Umwandlung (frisch Objekt). Ich weiß nicht, ob dies relevant ist oder nicht, aber ich hatte eine solche Anforderung.

@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)
        {

        }
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top