it-swarm.com.de

Beste Weg, um leere Daten zu behandeln

Ich versuche, eine Kontaktbuchanwendung zu erstellen, und arbeite derzeit an einer Klasse namens Person. Eines der Felder der Person ist dateOfBirth, ich weiß jedoch nicht, wie ich mit unbekannten Daten umgehen soll. Bis jetzt habe ich Java.time.LocalDate für dateOfBirth verwendet und das Feld bei der Instanziierung auf null initialisiert. Dies ist nicht ideal, da dies zu Nullzeigerausnahmen führt, wenn ich versuche, dateOfBirth mit anderen Daten wie LocalDate.now () zu vergleichen.

Was wäre der beste Weg, um mit dateOfBirth umzugehen? Sollte ich einfach eine völlig neue Klasse erstellen und unbekannte Daten intern verwalten? Oder gibt es einen besseren Weg, dies zu tun? Ich wollte nur LocalDate erweitern, aber es ist unveränderlich, kann also nicht erweitert werden, ohne zur Quelle zu gehen.

7
Helios

Verwenden Sie die Klasse Optional<LocalDate>

Diese nützliche Containerklasse wurde in Java 8.) eingeführt. Es handelt sich um einen Wrapper, der für Werte verwendet wird, die Sie möglicherweise kennen oder nicht kennen. Er ist mit verschiedenen Methoden entpackt, mit denen Sie den Fall behandeln können, dass die Wert ist auf anmutige Weise unbekannt.

  • get() entpackt das LocalDate, löst aber ein NoSuchElementException aus, falls Sie keines haben. Leider ist es eine ungeprüfte Ausnahme, genau wie das gefürchtete NullPointerException. Daher würde ich empfehlen, diese Methode zu vermeiden und stattdessen Folgendes zu verwenden:
  • orElseThrow(exception), die die Ausnahme auslöst, wenn Sie keinen Wert haben. Die Ausnahme kann (und sollte) eine aktivierte Ausnahme sein, sodass Sie gezwungen sind, damit umzugehen. Sie möchten kein klobiges try...catch... - Konstrukt schreiben? In diesem Fall:
  • ifPresent(Consumer<? super T> consumer) ist ein nützliches Konstrukt, wenn Sie Code nur ausführen möchten, wenn Sie einen Wert haben und ansonsten nichts tun.
  • orElse(T value) entpackt den Wert, erhält aber den Dummy-Wert, den Sie angeben, wenn Sie keinen haben

Weitere Informationen finden Sie im Artikel "Müde von Nullzeiger-Ausnahmen? Erwägen Sie die Verwendung von Java SE 8 ist optional!" in Oracle Tech Net und der Dokumentation um zu sehen, welche anderen Methoden es bietet.

Verwenden Sie Java 8 noch nicht?

Wenn Sie noch eine ältere Version von Java verwenden, können Sie leicht Ihre eigene OptionalDate -Klasse improvisieren, die nur Folgendes enthält:

  • private LocalDate
  • public void set(LocalDate value) und
  • public LocalDate get() throws DateUnknownException

Wenn der Getter eine aktivierte Ausnahme auslöst, müssen Sie immer den Null-Fall behandeln.

9
Philipp

Ihre Optionen sind:

1) Verwenden Sie null. Dann dürfen Sie nicht vergessen, nach Null zu suchen. Mit den Anmerkungen @NotNull Und @Nullable (Und ähnlichem) können Sie NullPointerException vermeiden.

2) Verwenden Sie Optional. Dies ist so, als müsste man nach Null suchen. Aber es fügt einige Overhead- und andere Indirektionen hinzu.

3) Verwenden Sie das DefaultObject-Muster: Erstellen Sie standardmäßig einen static final LocalDate DEFAULT. Ich mag das nicht, da man später leicht vergisst, dass man kein echtes, bekanntes Datum hat.

4) Verwenden Sie das NullObject-Muster: Erstellen Sie Ihre eigene Klasse, die ein Java.time.LocalDate umschließt, und definieren Sie dann anstelle von null: static final MyLocalDate UNKNOWN

5) Verwenden Sie eine Utility-Klasse, um Daten immer zu vergleichen oder zu verarbeiten. Anstelle von date1.foo(date2) würden Sie also UtilDates.foo(date1, date2) verwenden. Die Methode foo sollte Nullen akzeptieren.

Bevor Sie jedoch eine dieser Optionen auswählen, müssen Sie entscheiden, was zu tun ist, wenn Sie das Datum nicht kennen. Was möchten Sie beispielsweise tun, wenn Sie überprüfen, ob eine Person älter als 21 Jahre ist, das Geburtsdatum jedoch unbekannt ist? Möchten Sie immer davon ausgehen, dass die Person älter als 21 Jahre ist? Oder immer jünger als 21? Möchten Sie eine Warnung ausgeben und den aktuellen Vorgang abbrechen, um den Benutzer zur Eingabe eines Datums zu zwingen? Je nachdem, was Sie tun möchten, hat jede der oben genannten Optionen Vor- und Nachteile.

Es gibt noch eine andere, vielleicht keine Option in Ihrem Fall, aber:

6) Erzwingen Sie, dass der Benutzer ein gültiges Datum auswählt (d. H. Nullen nicht zulässt), wenn die Person instanziiert/gespeichert wird.

1
MarcG

Tony Hoare soll erfunden haben, was wir jetzt null nennen. Und er bereute es:

Ich nenne es meinen Milliardenfehler. Es war die Erfindung der Nullreferenz im Jahr 1965. Zu dieser Zeit entwarf ich das erste umfassende Typsystem für Referenzen in einer objektorientierten Sprache (ALGOL W). Mein Ziel war es sicherzustellen, dass jede Verwendung von Referenzen absolut sicher ist, wobei die Überprüfung automatisch vom Compiler durchgeführt wird. Aber ich konnte der Versuchung nicht widerstehen, eine Nullreferenz einzugeben, einfach weil es so einfach zu implementieren war. Dies hat zu unzähligen Fehlern, Schwachstellen und Systemabstürzen geführt, die in den letzten vierzig Jahren wahrscheinlich eine Milliarde Dollar an Schmerzen und Schäden verursacht haben

Quelle: Wikipedia .

Jetzt müssen wir leben und damit umgehen.

ich weiß jedoch nicht, wie ich mit unbekannten Daten umgehen soll.

Vertrau mir, du bist nicht allein.

Das Problem ist, dass es etwas gibt, das ich Mehrdeutigkeit von Informationen nennen würde. Fragen " wann war die Schlacht von Waterloo? " im Alltag " Ich weiß nicht "ist eine akzeptierte Antwort. Aber es geht nicht um die Antwort über das Datum selbst , es geht um das Wissen des Sprechers .

Zu Ihrem Problem: Wenn Sie person.getBirthDate() fragen, erhalten Sie eine mehrdeutige Antwort :

  • entweder war es am 1952-11-02

  • oder das Äquivalent zu Ich weiß nicht , was null ist.

Was ist eine richtige Lösung für das Elend der Mehrdeutigkeit ?

Da wir null haben und es in Datenspeichern weit verbreitet ist, sollten Sie null als richtige Antwort verwenden im Kontext der DB.

Aber was ist mit deinem Programm:

Wie du richtig gesagt hast

weil es zu Nullzeigerausnahmen führt, wenn ich versuche, dateOfBirth mit anderen Daten wie LocalDate.now () zu vergleichen

Sie müssen auf die eine oder andere Weise davor schützen:

1) Sie können einen Getter person.birthdayKnown() einführen, um Folgendes zu tun:

if (personA.birthdayKnown() && personA.birthdayKnown()) // allow further operations

2) Mit dem Aufkommen von Java8 können Sie es zu einem Optional machen und mit isPresent() arbeiten.

1
Thomas Junk

Wie @Philipp sagte, ist Optional eine gute Antwort auf dieses Problem. Es erfordert jedoch Java 8 (auch wenn Sie es selbst implementieren können), und diese Art von Struktur ist normalerweise für den funktionalen Programmierstil angepasst und kann daher in einem objektorientierten System seltsam erscheinen.

Eine typische OOP Alternative ist Null Object. Siehe zum Beispiel meine Antwort auf dieser andere Beitrag . Sie können ein "Standardverhalten" definieren, wenn das Objekt nicht festgelegt ist , was du willst.

0
mgoeminne