Einführung
NPE (NullPointerexception) ist die häufigste Ausnahme in Debugging -Programmen. Google hat viele Diskussionen darüber, ob die Methode NULL oder ein neues Objekt zurückgeben soll.
Lassen Sie uns zuerst zuerst über das NPE -Problem sprechen. Das NPE -Problem ist die NullPointerexception, der wir häufig in der Entwicklung begegnen. Angenommen, wir haben zwei Klassen, und ihr UML -Klassendiagramm ist in der folgenden Abbildung dargestellt
In diesem Fall gibt es den folgenden Code
user.getAddress (). getProvince ();
Diese Art des Schreibens kann eine NullPointerexception melden, wenn der Benutzer null ist. Um dieses Problem zu lösen, wird die folgende Schreibmethode angewendet
if (user! if (Adresse! }}
Dieser Schreibstil ist relativ hässlich. Um den oben genannten hässlichen Schreibstil zu vermeiden, wird das hässliche Design elegant. Java8 bietet eine optionale Klasse, um diese Schreibmethode zu optimieren, und der folgende Textabschnitt wird ausführlich erläutert.
API Einführung
Lassen Sie mich zuerst die API vorstellen. Im Gegensatz zu anderen Artikeln verwendet dieser Artikel eine Analogie -Methode und kombiniert den Quellcode. Im Gegensatz zu anderen Artikeln lässt jede API die Leute nicht die wichtigsten Punkte finden.
(1) optional (t -Wert), leer (), von (t -Wert), von nullierbar (t -Wert)
Diese vier Funktionen haben Korrelationen, daher werden sie in eine Gruppe für den Speicher platziert.
Lassen Sie mich zunächst erklären, dass der optionale (t -Wert), dh der Konstruktor, eine private Erlaubnis ist und nicht extern genannt werden kann. Die anderen drei Funktionen sind öffentliche Berechtigungen, die wir anrufen können. Dann besteht die Essenz des optionalen Unternehmens darin, einen realen Wert intern zu speichern, und beim Bau wird direkt beurteilt, ob sein Wert leer ist. Ok, das ist immer noch ziemlich abstrakt. Laden Sie den Quellcode des optionalen (T -Wert-) Konstruktors direkt hoch, wie in der folgenden Abbildung gezeigt
Dann lautet der Quellcode von (T -Wert) wie folgt
public static <t> optional <t> von (t value) {neu optional <> (Wert); } Mit anderen Worten, der Konstruktor wird intern nach der (t -Wert-) Funktion aufgerufen. Basierend auf dem Quellcode des Konstruktors können wir zwei Schlussfolgerungen ziehen:
(1) Wenn der Wert des Wertes leer ist, wird noch eine NullPointerexception gemeldet.
(2) Das optionale Objekt, das durch die Funktion von (t -Wert) konstruiert wurde, kann normal erstellt werden, wenn der Wertwert nicht leer ist.
Darüber hinaus verwaltet die optionale Klasse auch ein Objekt mit Value Null, wahrscheinlich wie die folgenden
public Final Class Optional <t> {// weglassen ...... private statische endgültige optionale <?> leer = neo optional <> (); private optional () {this.Value = null; } // weglassen ... public static <T> optional <t> leer () {@Suppresswarnings ("deaktiviert") Optional <t> T = (optional <t>) leer; return t; }} Dann besteht die Funktion von leer () darin, das leere Objekt zurückzugeben.
Nun, so viele Vorbereitungen wurden gelegt. Es kann gesagt werden, dass von Nullierbar (T -Wert) die Funktion hat und der Quellcode hinzugefügt wird.
public static <t> Optional <t> von nullable (t -Wert) {return value == null? leer (): von (Wert); } Nun, jeder sollte verstehen, was es bedeutet. Die Differenzvergleich zu (T -Wert) besteht darin, dass, wenn der Wertwert null ist, von (t -Wert) eine Nullpointerexception meldet; Ofnullable (t -Wert) wirft keine Ausnahme aus, von nullierbar (t -Wert) gibt direkt ein leeres Objekt zurück.
Bedeutet das, dass wir nur eine nullbare Funktion anstelle von Funktionen in unserem Projekt verwenden?
Nein, wenn etwas existiert, dann wird es natürlich einen Wert haben. Wenn wir laufen, wollen wir NullPointerexception nicht verbergen. Stattdessen müssen Sie sofort melden und in diesem Fall die Funktion verwenden. Aber ich muss zugeben, dass es wirklich wenige solcher Szenen gibt. Der Blogger hat diese Funktion nur beim Schreiben von Junit -Testfällen verwendet.
.
Diese drei Funktionen werden in einer Gruppe auswendig gelernt und werden aufgerufen, wenn der vom Konstruktor übergebene Wert null ist. Die Verwendung von Orelse und Orelseget ist wie folgt. Wenn der Wert null ist, wird ein Standardwert angegeben:
@Testpublic void test () {user user = null; user = optional.ofnullable (Benutzer) .orelse (createUser ()); user = optional.ofnullable (user) .orelseget (() -> createUser ()); } public user createUser () {user user = new user (); user.setName ("Zhangsan"); Benutzer zurückgeben;} Der Unterschied zwischen diesen beiden Funktionen: Wenn der Benutzerwert nicht null ist, wird die Orelse -Funktion weiterhin die Methode createUser () ausführen, während die Orelseget -Funktion die Methode createUser () nicht ausführt, sodass Sie sie selbst testen können.
Was Orelsethrow betrifft, wird eine Ausnahme direkt rausgeschmissen, wenn der Wert null ist. Die Verwendung ist wie folgt
User user = null; optional.ofnullable (Benutzer) .Orelsethrow (()-> Neue Ausnahme ("Benutzer nicht existiert"));(3) MAP (Funktion <? Super t,? Erweitert U> Mapper) und FlatMap (Funktion <? Super t, optional <u >> Mapper)
Diese beiden Funktionen werden in einen Speichersatz platziert, und diese beiden Funktionen haben den Betrieb der Konvertierungswerte.
Laden Sie den Quellcode direkt hoch hoch
public Final Class Optional <t> {// weglassen ...... public <U> optional <u> map (Funktion <? Super t,? Erweitert u> mapper) {Objects.requirenonnull (Mapper); if (! isPresent ()) kehre leer zurück (); sonst {return optional.ofnulable (mapper.apply (Wert)); }} // weglassen ... public <U> optional <u> flatMap (Funktion <? Super T, optional <u >> mapper) {Objects.requirenonnull (Mapper); if (! isPresent ()) kehre leer zurück (); sonst {return objects.requirenonnull (Mapper.Apply (Wert)); }}} Es gibt keinen Unterschied zwischen diesen beiden Funktionen im Körper der Funktion. Der einzige Unterschied ist der Eingabeparameter. Der von der Kartenfunktion akzeptierte Eintragsparametertyp ist Funktion <? Super t,? Erweitert U>, während der Flapmap -Typ des Eintragsparameters Funktion <? Super t, optional <u >>.
In Bezug auf die spezifische Verwendung für Karte:
Wenn die Benutzerstruktur wie folgt ist
public class user {private Zeichenfolge Name; public String getName () {return name; }}Zu diesem Zeitpunkt ist die Schreibmethode zum Namen der Namen wie folgt
String City = optional.ofnullable (Benutzer) .MAP (u-> u.getName ()). Get ();
Für FlatMap:
Wenn die Benutzerstruktur wie folgt ist
public class user {private Zeichenfolge Name; public optional <string> getName () {return optional.ofnullable (name); }}Zu diesem Zeitpunkt ist die Schreibmethode zum Namen der Namen wie folgt
String City = optional.ofnullable (Benutzer) .flatMap (u-> u.getName ()). Get ();
(4) isPresent () und ifpresent (Verbraucher <? Super t> Verbraucher)
Stellen Sie diese beiden Funktionen zusammen und merken Sie sie. ISPRESET -Mittel, um festzustellen, ob der Wert leer ist, und wenn es sich um einige Operationen handelt, wenn der Wert nicht leer ist. Die Quellcodes dieser beiden Funktionen sind wie folgt
public Final Class Optional <t> {// weglassen ...... public boolean iSPresent () {return value! = null; } // weglassen ... public void ifPresent (Verbraucher <? Super t> Verbraucher) {if (value! = Null) Consumer.accept (value); }}Es braucht zusätzliche Erklärung, nicht
if (user! = null) {// todo: mach etwas}Geschrieben
User user = optional.ofnullable (user); if (optional.Spresent ()) {// toDo: mach etwas} Aus diesem Grund ist die Codestruktur immer noch hässlich. Der Blogger wird später die richtige Schreibmethode angeben
Was IfPresent (Consumer <? Super t> Consumer) betrifft, ist die Verwendung auch sehr einfach, wie unten gezeigt
Optional.ofnullable (Benutzer) .ifpresent (u-> {// toDo: mach etwas});(5) Filter (Prädikat <? Super t> Predictate)
Laden Sie ohne weiteres den Quellcode hoch hoch
öffentliche endgültige Klasse Optional <t> {// weglassen ...... Objects.requirenonnull (Prädikat); if (! isPresent ()) gibt dies zurück; sonst return predict.test (Wert)? Dies: leer ();} Die Filtermethode akzeptiert ein Prädikat, um die in optionalen enthaltenen Werte zu filtern. Wenn die enthaltenen Werte den Bedingungen erfüllen, wird das Optional weiterhin zurückgegeben. Andernfalls wird das optionale. empty zurückgegeben.
Die Verwendung ist wie folgt
Optional <Benutzer> user1 = optional.ofnullable (Benutzer) .Filter (u -> u.getName (). Länge () <6);
Wie oben gezeigt, kehren Sie, wenn die Länge des Benutzernamens weniger als 6 beträgt, zurück. Wenn es größer als 6 ist, wird ein leeres Objekt zurückgegeben.
Praktische Verwendung
Beispiel 1
In Funktionsmethode
Vorheriges Schreiben
public String getCity (Benutzer Benutzer) löst Ausnahme aus {if (user! = null) {if (user.getAddress ()! if (address.getCity ()! = null) {return address.getCity (); }}} Neue Aufpetion werfen ("Wertfehler"); }Java8 Schreibmethode
public String getCity (Benutzer Benutzer) löst Ausnahme aus {return optional.ofnullable (Benutzer) .MAP (u-> u.getAddress ()) .MAP (a-> a.getCity ()) .Orelsethrow (()-> Neue Ausnahme ("Fetch-Fehler");}Beispiel 2
Zum Beispiel im Hauptprogramm
Vorheriges Schreiben
if (user! = null) {dosomething (user);}Java8 Schreibmethode
Optional.ofnullable (Benutzer) .ifpresent (u-> {doSomething (u);});Beispiel 3
Vorheriges Schreiben
public user getUser (Benutzer Benutzer) löst Ausnahme aus {if (user! = null) {String name = user.getName (); if ("zhangsan" .equals (name)) {zurücksender Benutzer; }} else {user = new user (); user.setName ("Zhangsan"); Benutzer zurückgeben; }}Java8 Schreibmethode
public user getUser (user user) {return optional.ofnullable (user) .filter (u-> "zhangsan" .equals (u.getName ()) .Orelseget (()-> {user user1 = new User; user1.setname ("ZHANGSAN");Andere Beispiele werden nacheinander nicht aufgeführt. Der Blogger ist jedoch der Ansicht, dass die Verwendung dieser Kettenprogrammierung im Code tatsächlich elegant ist. Die Logik ist jedoch nicht so offensichtlich und die Lesbarkeit wird verringert. Wir verwenden es gemäß der Situation im Projekt.
Zusammenfassen
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels einen gewissen Referenzwert für das Studium oder die Arbeit eines jeden hat. Wenn Sie Fragen haben, können Sie eine Nachricht zur Kommunikation überlassen. Vielen Dank für Ihre Unterstützung bei Wulin.com.