Java 8 Optional im Detail
Java 8 hat eine neue Klasse Optional im Paket java.util eingeführt. Es wird verwendet, um darzustellen, dass ein Wert vorhanden oder nicht vorhanden ist. Der Hauptvorteil dieses neuen Konstrukts besteht darin, dass nicht mehr zu viele Nullprüfungen undNullPointerException
durchgeführt werden. Es vermeidet jede LaufzeitNullPointerExceptions
und unterstützt uns bei der Entwicklung sauberer und ordentlicher Java-APIs oder -Anwendungen. Wie Sammlungen und Arrays ist es auch ein Container, der höchstens einen Wert enthält. Lassen Sie uns dieses neue Konstrukt anhand einiger nützlicher Beispiele untersuchen.
Vorteile von Java 8 Optional:
-
Nullprüfungen sind nicht erforderlich.
-
Keine NullPointerException mehr zur Laufzeit.
-
Wir können saubere und ordentliche APIs entwickeln.
-
Kein Kesselschildcode mehr
1. Optionales Basisbeispiel
Die MethodeOptional.ofNullable()
gibt eine nicht leere Option zurück, wenn ein Wert im angegebenen Objekt vorhanden ist. Andernfalls wird leer zurückgegeben. Optional.
Die Methode vonOptionaal.empty()
ist nützlich, um ein leeres optionales Objekt zu erstellen.
OptionalBasicExample.java
package com.example; import java.util.Optional; public class OptionalBasicExample { public static void main(String[] args) { Optionalgender = Optional.of("MALE"); String answer1 = "Yes"; String answer2 = null; System.out.println("Non-Empty Optional:" + gender); System.out.println("Non-Empty Optional: Gender value : " + gender.get()); System.out.println("Empty Optional: " + Optional.empty()); System.out.println("ofNullable on Non-Empty Optional: " + Optional.ofNullable(answer1)); System.out.println("ofNullable on Empty Optional: " + Optional.ofNullable(answer2)); // java.lang.NullPointerException System.out.println("ofNullable on Non-Empty Optional: " + Optional.of(answer2)); } }
Ausgabe
Non-Empty Optional:Optional[MALE] Non-Empty Optional: Gender value : MALE Empty Optional: Optional.empty ofNullable on Non-Empty Optional: Optional[Yes] ofNullable on Empty Optional: Optional.empty Exception in thread "main" java.lang.NullPointerException at java.util.Objects.requireNonNull(Objects.java:203) at java.util.Optional.(Optional.java:96) at java.util.Optional.of(Optional.java:108) //...
2. Optional.map and flatMap
OptionalMapFlapMapExample.java
package com.example; import java.util.Optional; public class OptionalMapFlapMapExample { public static void main(String[] args) { OptionalnonEmptyGender = Optional.of("male"); Optional emptyGender = Optional.empty(); System.out.println("Non-Empty Optional:: " + nonEmptyGender.map(String::toUpperCase)); System.out.println("Empty Optional :: " + emptyGender.map(String::toUpperCase)); Optional > nonEmptyOtionalGender = Optional.of(Optional.of("male")); System.out.println("Optional value :: " + nonEmptyOtionalGender); System.out.println("Optional.map :: " + nonEmptyOtionalGender.map(gender -> gender.map(String::toUpperCase))); System.out.println("Optional.flatMap :: " + nonEmptyOtionalGender.flatMap(gender -> gender.map(String::toUpperCase))); } }
Ausgabe
Non-Empty Optional:: Optional[MALE] Empty Optional :: Optional.empty Optional value :: Optional[Optional[male]] Optional.map :: Optional[Optional[MALE]] Optional.flatMap :: Optional[MALE]
3. Optional.filter
OptionalFilterExample.java
package com.example; import java.util.Optional; public class OptionalFilterExample { public static void main(String[] args) { Optionalgender = Optional.of("MALE"); Optional emptyGender = Optional.empty(); //Filter on Optional System.out.println(gender.filter(g -> g.equals("male"))); //Optional.empty System.out.println(gender.filter(g -> g.equalsIgnoreCase("MALE"))); //Optional[MALE] System.out.println(emptyGender.filter(g -> g.equalsIgnoreCase("MALE"))); //Optional.empty } }
Ausgabe
Optional.empty Optional[MALE] Optional.empty
4. Optional isPresent und ifPresent
Optional.isPresent()
gibt true zurück, wenn das angegebene optionale Objekt nicht leer ist. Andernfalls wird false zurückgegeben.
Optional.ifPresent()
führt eine bestimmte Aktion aus, wenn das angegebene optionale Objekt nicht leer ist. Andernfalls wird false zurückgegeben.
OptionalIfPresentExample.java
package com.example; import java.util.Optional; public class OptionalIfPresentExample { public static void main(String[] args) { Optionalgender = Optional.of("MALE"); Optional emptyGender = Optional.empty(); if (gender.isPresent()) { System.out.println("Value available."); } else { System.out.println("Value not available."); } gender.ifPresent(g -> System.out.println("In gender Option, value available.")); //condition failed, no output print emptyGender.ifPresent(g -> System.out.println("In emptyGender Option, value available.")); } }
Ausgabe
Value available. In gender Option, value available.
5. Optionale oderElse-Methoden
Es gibt den Wert zurück, falls dieser im optionalen Container vorhanden ist. Andernfalls wird der angegebene Standardwert zurückgegeben.
OptionalOrElseExample.java
package com.example; import java.util.Optional; public class OptionalOrElseExample { public static void main(String[] args) { Optionalgender = Optional.of("MALE"); Optional emptyGender = Optional.empty(); System.out.println(gender.orElse(" ")); //MALE System.out.println(emptyGender.orElse(" ")); // System.out.println(gender.orElseGet(() -> " ")); //MALE System.out.println(emptyGender.orElseGet(() -> " ")); // } }
Ausgabe
MALEMALE
6. Ohne Java 8 Optional
Wie jeder mit Online-Shopping vertraut ist. Nehmen wir an, wir möchten ein mobiles Produktmodul für eine bekannte E-Commerce-Website implementieren.
Lassen Sie uns das Mobile Domain-Modul ohne Java 8 Optional implementieren.
ScreenResolution.java
package com.example.without.optional; public class ScreenResolution { private int width; private int height; public ScreenResolution(int width, int height){ this.width = width; this.height = height; } public int getWidth() { return width; } public int getHeight() { return height; } }
DisplayFeatures.java
package com.example.without.optional; public class DisplayFeatures { private String size; // In inches private ScreenResolution resolution; public DisplayFeatures(String size, ScreenResolution resolution){ this.size = size; this.resolution = resolution; } public String getSize() { return size; } public ScreenResolution getResolution() { return resolution; } }
Mobile.java
package com.example.without.optional; public class Mobile { private long id; private String brand; private String name; private DisplayFeatures displayFeatures; // Likewise we can see Memory Features, Camera Features etc. public Mobile(long id, String brand, String name, DisplayFeatures displayFeatures){ this.id = id; this.brand = brand; this.name = name; this.displayFeatures = displayFeatures; } public long getId() { return id; } public String getBrand() { return brand; } public String getName() { return name; } public DisplayFeatures getDisplayFeatures() { return displayFeatures; } }
Wenn wir hier diegetMobileScreenWidth()
-Methode beobachten, hat sie viel Kesselplattencode mit vielen Nullprüfungen. Vor Java 8 sollten wir all diese unsinnigen Dinge tun, um Runtime NullPointerExceptions zu vermeiden.
MobileService.java
package com.example.without.optional; public class MobileService { public int getMobileScreenWidth(Mobile mobile){ if(mobile != null){ DisplayFeatures dfeatures = mobile.getDisplayFeatures(); if(dfeatures != null){ ScreenResolution resolution = dfeatures.getResolution(); if(resolution != null){ return resolution.getWidth(); } } } return 0; } }
Entwickeln Sie eine Testanwendung, um diese Domänenobjekte zu testen.
MobileTesterWithoutOptional.java
package com.example.without.optional; public class MobileTesterWithoutOptional { public static void main(String[] args) { ScreenResolution resolution = new ScreenResolution(750,1334); DisplayFeatures dfeatures = new DisplayFeatures("4.7", resolution); Mobile mobile = new Mobile(2015001, "Apple", "iPhone 6s", dfeatures); MobileService mService = new MobileService(); int mobileWidth = mService.getMobileScreenWidth(mobile); System.out.println("Apple iPhone 6s Screen Width = " + mobileWidth); ScreenResolution resolution2 = new ScreenResolution(0,0); DisplayFeatures dfeatures2 = new DisplayFeatures("0", resolution2); Mobile mobile2 = new Mobile(2015001, "Apple", "iPhone 6s", dfeatures2); int mobileWidth2 = mService.getMobileScreenWidth(mobile2); System.out.println("Apple iPhone 16s Screen Width = " + mobileWidth2); } }
Ausgabe
Apple iPhone 6s Screen Width = 750 Apple iPhone 16s Screen Width = 0
7. Mit Java 8 Optional
Entwickeln Sie jetzt dieselben Domänenmodelle mithilfe des optionalen Java 8-Konstrukts.
P.S ScreenResolution.java
no change. Bitte beachten Sie den obigen Abschnitt.
DisplayFeatures.java
package com.example.with.optional; import java.util.Optional; public class DisplayFeatures { private String size; // In inches private Optionalresolution; public DisplayFeatures(String size, Optional resolution){ this.size = size; this.resolution = resolution; } public String getSize() { return size; } public Optional getResolution() { return resolution; } }
Mobile.java
package com.example.with.optional; import java.util.Optional; public class Mobile { private long id; private String brand; private String name; private OptionaldisplayFeatures; // Like wise we can see MemoryFeatures, CameraFeatures etc. // For simplicity, using only one Features public Mobile(long id, String brand, String name, Optional displayFeatures){ this.id = id; this.brand = brand; this.name = name; this.displayFeatures = displayFeatures; } public long getId() { return id; } public String getBrand() { return brand; } public String getName() { return name; } public Optional getDisplayFeatures() { return displayFeatures; } }
Hier können wir beobachten, wie sauber unseregetMobileScreenWidth()
API ohne Nullprüfungen und Kesselplattencode ist. Wir kümmern uns nicht um NullPointerExceptions zur Laufzeit.
MobileService.java
package com.example.with.optional; import java.util.Optional; public class MobileService { public Integer getMobileScreenWidth(Optionalmobile){ return mobile.flatMap(Mobile::getDisplayFeatures) .flatMap(DisplayFeatures::getResolution) .map(ScreenResolution::getWidth) .orElse(0); } }
Entwickeln Sie nun eine Testkomponente
MobileTesterWithOptional.java
package com.example.with.optional; import java.util.Optional; public class MobileTesterWithOptional { public static void main(String[] args) { ScreenResolution resolution = new ScreenResolution(750,1334); DisplayFeatures dfeatures = new DisplayFeatures("4.7", Optional.of(resolution)); Mobile mobile = new Mobile(2015001, "Apple", "iPhone 6s", Optional.of(dfeatures)); MobileService mService = new MobileService(); int width = mService.getMobileScreenWidth(Optional.of(mobile)); System.out.println("Apple iPhone 6s Screen Width = " + width); Mobile mobile2 = new Mobile(2015001, "Apple", "iPhone 6s", Optional.empty()); int width2 = mService.getMobileScreenWidth(Optional.of(mobile2)); System.out.println("Apple iPhone 16s Screen Width = " + width2); } }
Ausgabe
Apple iPhone 6s Screen Width = 750 Apple iPhone 16s Screen Width = 0
8. Wo passt Java Optional hin?
Wenn wir den obigen Anwendungsfall für Echtzeit-Retail-Domains beobachten, sollten wir wissen, dass das optionale Java-Konstrukt an den folgenden Stellen nützlich ist.
8.1 Method Parameter
public void setResolution(Optionalresolution) { this.resolution = resolution; }
8.2 Method Return Type
public OptionalgetResolution() { return resolution; }
8.3 Constructor Parameter
public DisplayFeatures(String size, Optionalresolution){ this.size = size; this.resolution = resolution; }
8.4 Variable Declaration
private Optionalresolution;
8.5 Class Level
public class B public class A> { }
Quellcode herunterladen
Herunterladen -Java8Optional-example.zip (4 KB)