Das Fangen NullPointerException
ist sehr problematisch, da es fast überall passieren kann. Es ist sehr einfach, einen Fehler zu beheben, ihn versehentlich zu erkennen und so fortzufahren, als ob alles normal wäre, wodurch ein echtes Problem verborgen bleibt. Es ist so schwierig damit umzugehen, deshalb ist es am besten, es ganz zu vermeiden. (Denken Sie beispielsweise an das automatische Entpacken einer Null Integer
.)
Ich schlage vor, dass Sie Optional
stattdessen die Klasse verwenden. Dies ist häufig der beste Ansatz, wenn Sie mit vorhandenen oder fehlenden Werten arbeiten möchten.
Damit könnten Sie Ihren Code folgendermaßen schreiben:
public Optional<Integer> m(Ws wsObject) {
return Optional.ofNullable(wsObject.getFoo()) // Here you get Optional.empty() if the Foo is null
.map(f -> f.getBar()) // Here you transform the optional or get empty if the Bar is null
.map(b -> b.getBaz())
.map(b -> b.getInt());
// Add this if you want to return null instead of an empty optional if any is null
// .orElse(null);
// Or this if you want to throw an exception instead
// .orElseThrow(SomeApplicationException::new);
}
Warum optional?
Die Verwendung von Optional
s anstelle von null
Werten, die möglicherweise nicht vorhanden sind, macht diese Tatsache für die Leser sehr sichtbar und klar, und das Typsystem stellt sicher, dass Sie sie nicht versehentlich vergessen.
Sie erhalten auch Zugriff auf Methoden zum bequemeren Arbeiten mit solchen Werten, wie z map
und orElse
.
Ist Abwesenheit gültig oder Fehler?
Denken Sie aber auch darüber nach, ob es ein gültiges Ergebnis für die Zwischenmethoden ist, null zurückzugeben, oder ob dies ein Zeichen für einen Fehler ist. Wenn es sich immer um einen Fehler handelt, ist es wahrscheinlich besser, eine Ausnahme auszulösen, als einen speziellen Wert zurückzugeben, oder dass die Zwischenmethoden selbst eine Ausnahme auslösen.
Vielleicht mehr Optionen?
Wenn andererseits fehlende Werte aus den Zwischenmethoden gültig sind, können Sie möglicherweise zu wechseln Optional
für sie s ?
Dann könnten Sie sie so verwenden:
public Optional<Integer> mo(Ws wsObject) {
return wsObject.getFoo()
.flatMap(f -> f.getBar())
.flatMap(b -> b.getBaz())
.flatMap(b -> b.getInt());
}
Warum nicht optional?
Der einzige Grund, warum ich daran denken kann, nicht zu verwenden, Optional
ist, wenn dies ein wirklich leistungskritischer Teil des Codes ist und sich herausstellt, dass der Aufwand für die Speicherbereinigung ein Problem darstellt. Dies liegt daran Optional
, dass bei jeder Ausführung des Codes einige Objekte zugewiesen werden und die VM diese möglicherweise nicht optimieren kann. In diesem Fall könnten Ihre ursprünglichen Wenn-Tests besser sein.
null
Überprüfungen würden mir nicht so viel ausmachen, dawsObject.getFoo().getBar().getBaz().getInt()
es bereits nach Code riecht. Lesen Sie, was das "Gesetz von Demeter" ist, und ziehen Sie es vor, Ihren Code entsprechend umzugestalten. Dann ist auch das Problem mit dennull
Prüfungen verschwunden. Und denken Sie darüber nach, zu verwendenOptional
.