Java 8 опционально по глубине
Java 8 представила новый класс Optional в пакете java.util. Используется для представления значения, присутствует или отсутствует. Основное преимущество этой новой конструкции состоит в том, что больше не нужно слишком много проверок на null иNullPointerException. Он избегает использованияNullPointerExceptionsво время выполнения и поддерживает нас в разработке чистых и аккуратных Java API или приложений. Как и Коллекции и массивы, это также Контейнер для хранения не более одного значения. Давайте рассмотрим эту новую конструкцию с некоторыми полезными примерами.
Преимущества Java 8 Необязательно:
-
Нулевые проверки не требуются.
-
Нет больше NullPointerException во время выполнения.
-
Мы можем разработать чистые и аккуратные API.
-
Нет больше кода котельной плиты
1. Необязательный базовый пример
МетодOptional.ofNullable() возвращает непустой Optional, если значение присутствует в данном объекте. В противном случае возвращает пустой Необязательно.
МетодOptionaal.empty() полезен для создания пустого необязательного объекта.
OptionalBasicExample.java
package com.example;
import java.util.Optional;
public class OptionalBasicExample {
public static void main(String[] args) {
Optional gender = 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));
}
}
Выход
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) {
Optional nonEmptyGender = 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)));
}
}
Выход
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) {
Optional gender = 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
}
}
Выход
Optional.empty Optional[MALE] Optional.empty
4. Необязательный isPresent и ifPresent
Optional.isPresent() возвращает истину, если данный необязательный объект не пуст. В противном случае возвращается false.
Optional.ifPresent() выполняет заданное действие, если заданный необязательный объект не пуст. В противном случае возвращается false.
OptionalIfPresentExample.java
package com.example;
import java.util.Optional;
public class OptionalIfPresentExample {
public static void main(String[] args) {
Optional gender = 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."));
}
}
Выход
Value available. In gender Option, value available.
5. Необязательные методы orElse
Возвращает значение, если оно присутствует в дополнительном контейнере. В противном случае возвращает заданное значение по умолчанию.
OptionalOrElseExample.java
package com.example;
import java.util.Optional;
public class OptionalOrElseExample {
public static void main(String[] args) {
Optional gender = 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(() -> "")); //
}
}
Выход
MALEMALE
6. Без Java 8 Необязательно
Как все знакомы с интернет-магазинами. Предположим, мы хотим внедрить модуль мобильного продукта для известного веб-сайта электронной коммерции.
Давайте реализуем модуль Мобильный домен без Java 8 Необязательно.
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;
}
}
Здесь, если мы наблюдаем методgetMobileScreenWidth(), он имеет много шаблонного кода с множеством нулевых проверок. До Java 8 мы должны делать все эти бессмысленные вещи, чтобы избежать Runtime NullPointerExceptions.
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;
}
}
Разработайте одно тестовое приложение для тестирования этих объектов Домена.
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);
}
}
Выход
Apple iPhone 6s Screen Width = 750 Apple iPhone 16s Screen Width = 0
7. С Java 8 необязательно
Теперь разработайте те же доменные модели, используя Java 8 Optional, аккуратно и аккуратно.
P.S ScreenResolution.java no change. См. Раздел выше.
DisplayFeatures.java
package com.example.with.optional;
import java.util.Optional;
public class DisplayFeatures {
private String size; // In inches
private Optional resolution;
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 Optional displayFeatures;
// 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;
}
}
Здесь мы можем наблюдать, как очистить наш APIgetMobileScreenWidth() без нулевых проверок и кода шаблона. Мы не беспокоимся об исключениях NullPointerException во время выполнения.
MobileService.java
package com.example.with.optional;
import java.util.Optional;
public class MobileService {
public Integer getMobileScreenWidth(Optional mobile){
return mobile.flatMap(Mobile::getDisplayFeatures)
.flatMap(DisplayFeatures::getResolution)
.map(ScreenResolution::getWidth)
.orElse(0);
}
}
Теперь разработайте один тестовый компонент
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);
}
}
Выход
Apple iPhone 6s Screen Width = 750 Apple iPhone 16s Screen Width = 0
8. Где подходит Java Optional?
Если мы наблюдаем приведенный выше пример использования розничного домена в реальном времени, мы должны знать, что опциональная конструкция Java полезна в следующих местах
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> { }
Скачать исходный код
Скачать -Java8Optional-example.zip (4 КБ)