Java 8 опционально по глубине

Java 8 опционально по глубине

Java 8 представила новый класс Optional в пакете java.util. Используется для представления значения, присутствует или отсутствует. Основное преимущество этой новой конструкции состоит в том, что больше не нужно слишком много проверок на null иNullPointerException. Он избегает использованияNullPointerExceptionsво время выполнения и поддерживает нас в разработке чистых и аккуратных Java API или приложений. Как и Коллекции и массивы, это также Контейнер для хранения не более одного значения. Давайте рассмотрим эту новую конструкцию с некоторыми полезными примерами.

Преимущества Java 8 Необязательно:

  1. Нулевые проверки не требуются.

  2. Нет больше NullPointerException во время выполнения.

  3. Мы можем разработать чистые и аккуратные API.

  4. Нет больше кода котельной плиты

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(() -> "")); //

    }

}

Выход

MALE

MALE

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(Optional resolution) {
    this.resolution = resolution;
}

8.2 Method Return Type

public Optional getResolution() {
    return resolution;
}

8.3 Constructor Parameter

public DisplayFeatures(String size, Optional resolution){
    this.size = size;
    this.resolution = resolution;
}

8.4 Variable Declaration

private Optional resolution;

8.5 Class Level

public class B

public class A> { }

Скачать исходный код

Скачать -Java8Optional-example.zip (4 КБ)

Рекомендации