Java 8 Facultatif en profondeur

Java 8 en profondeur en option

Java 8 a introduit une nouvelle classe facultative dans le package java.util. Il est utilisé pour représenter une valeur présente ou absente. Le principal avantage de cette nouvelle construction est qu'il n'y a plus trop de vérifications nulles et deNullPointerException. Il évite tout runtimeNullPointerExceptions et nous aide à développer des API ou applications Java propres et soignées. Comme les collections et les tableaux, il s'agit également d'un conteneur contenant au plus une valeur. Explorons cette nouvelle construction avec quelques exemples utiles.

Avantages de Java 8 en option:

  1. Aucun contrôle nul n'est requis.

  2. Plus d'exception NullPointerException au moment de l'exécution.

  3. Nous pouvons développer des API propres et soignées.

  4. Plus de code de plaque de chaudière

1. Exemple de base facultatif

La méthodeOptional.ofNullable() renvoie une option non vide si une valeur est présente dans l'objet donné. Sinon, renvoie vide Facultatif.

La méthodeOptionaal.empty() est utile pour créer un objet facultatif vide.

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));

    }

}

Sortie

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)));

    }

}

Sortie

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

    }

}

Sortie

Optional.empty
Optional[MALE]
Optional.empty

4. Facultatif isPresent et ifPresent

Optional.isPresent() renvoie vrai si l'objet facultatif donné n'est pas vide. Sinon, elle renvoie faux.

Optional.ifPresent() exécute une action donnée si l'objet optionnel donné n'est pas vide. Sinon, elle renvoie faux.

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."));

    }

}

Sortie

Value available.
In gender Option, value available.

5. Méthodes orElse facultatives

Il renvoie la valeur si elle est présente dans le conteneur facultatif. Sinon, renvoie la valeur par défaut donnée.

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

    }

}

Sortie

MALE

MALE

6. Sans Java 8 en option

Comme tout le monde connaît les achats en ligne. Supposons que nous voulons implémenter un module de produit mobile pour un célèbre site Web de commerce électronique.

Implémentons le module Mobile Domain sans Java 8 en option.

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;
    }

}

Ici, si nous observons la méthodegetMobileScreenWidth(), il y a beaucoup de code de plaque de chaudière avec beaucoup de vérifications nulles. Avant Java 8, nous devons faire toutes ces choses non sensées pour éviter les exceptions 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;

    }

}

Développez une application de test pour tester ces objets de domaine.

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);

    }

}

Sortie

Apple iPhone 6s Screen Width = 750
Apple iPhone 16s Screen Width = 0

7. Avec Java 8 en option

Développez maintenant les mêmes modèles de domaine à l'aide de la construction facultative Java 8 de manière propre et soignée.

P.S ScreenResolution.java no change. Veuillez vous référer à la section ci-dessus.

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;
    }

}

Ici, nous pouvons observer comment nettoyer notre APIgetMobileScreenWidth() sans contrôle nul et code de plaque de chaudière. Nous ne nous inquiétons pas des NullPointerExceptions au moment de l'exécution.

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);

  }

}

Développer maintenant un composant de test

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);
  }
}

Sortie

Apple iPhone 6s Screen Width = 750
Apple iPhone 16s Screen Width = 0

8. Où se situe Java Optional?

Si nous observons le cas d'utilisation de Retail Domain en temps réel ci-dessus, nous devons savoir que la construction Java Optional est utile aux endroits suivants.

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> { }

Télécharger le code source

Télécharger -Java8Optional-example.zip (4 KB)

Références