Nouvelles fonctionnalités du JDK8 - Explication détaillée de l'utilisation de la classe facultative

I. Aperçu

        Je pense que NullPointerException est familière à tous les programmeurs JAVA et constitue l'exception la plus courante dans les applications JAVA. Auparavant, le projet Google Guava proposait d'utiliser la classe Facultative pour envelopper des objets afin de résoudre NullPointerException. Affectée par cela, la classe Facultative a également été introduite dans les classes JDK8 et la prise en charge de cette méthode a été implémentée dans la nouvelle version de SpringData Jpa et Spring Redis Data.

2. Cours optionnel

/**
 * A container object which may or may not contain a non-null value.
 * If a value is present, {@code isPresent()} will return {@code true} and
 * {@code get()} will return the value.
 *
 * @since 1.8
 */
public final class Optional<T> {
    /**
     * Common instance for {@code empty()}.
     */
    private static final Optional<?> EMPTY = new Optional<>();

    /**
     * If non-null, the value; if null, indicates no value is present
     */
    private final T value;

   // 其他省略
}

L'annotation de cette méthode signifie en gros : Facultatif est un objet conteneur, qui peut contenir des valeurs nulles ou non nulles. Lorsque la valeur de l'attribut est définie, la méthode isPesent() renverra true et la méthode get() renverra cette valeur. ​ Cette classe prend en charge les génériques, c'est-à-dire que sa valeur d'attribut peut être une instance de n'importe quel objet.

3. Méthodes de classe facultative

numéro de série méthode Description de la méthode
1 private Optional() Construction sans paramètre, construit un vide Facultatif
2 private Optional(T value) Construire un facultatif basé sur la valeur non vide transmise
3 public static<T> Optional<T> empty() Renvoie un vide Facultatif, la valeur de cette instance est vide
4 public static <T> Optional<T> of(T value) Construisez un facultatif basé sur la valeur non vide transmise, ce qui a le même effet que la méthode facultatif (valeur T)
5 public static <T> Optional<T> ofNullable(T value) Différent de la méthode of(T value), ofNullable(T value) vous permet de transmettre une valeur vide. Lorsque la valeur transmise est une valeur nulle, elle crée un facultatif vide. Lorsque la valeur transmise n'est pas vide, elle est le même que of. () a le même effet
6 public T get() Renvoie la valeur de Facultatif. Si le conteneur est vide, une NoSuchElementException est levée.
7 public boolean isPresent() Déterminer si la valeur du paramètre Facultatif du propriétaire a été définie
8 public void ifPresent(Consumer<? super T> consumer) Déterminez si l'option du propriétaire a défini une valeur. S'il existe une valeur, appelez l'interface fonctionnelle Consommateur pour le traitement.
9 public Optional<T> filter(Predicate<? super T> predicate) Si une valeur est définie et que les conditions de jugement de Predicate sont remplies, l'optionnel est renvoyé, sinon un facultatif vide est renvoyé.
dix public<U> Optional<U> map(Function<? super T, ? extends U> mapper) Si Facultatif définit une valeur, appelez Function pour traiter la valeur et renvoie un Facultatif contenant la valeur traitée, sinon un Facultatif vide est renvoyé.
11 public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) Différent du type de méthode map(), son résultat de mappeur est déjà facultatif et il n’est pas nécessaire d’envelopper le résultat.
12 public T orElse(T other) Si la valeur facultative n'est pas vide, renvoyez cette valeur, sinon renvoyez d'autres
13 public T orElseGet(Supplier<? extends T> other) Si la valeur Optionnelle n'est pas vide, renvoyez cette valeur, sinon générez-en une autre basée sur d'autres
14 public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)throws X Si la valeur facultative n'est pas vide, renvoyez la valeur, sinon lancez une exception via le fournisseur.

4. Exemples de méthodes de la classe Optionnel

Premier exemple :

public static void main(String[] args) {
  Optional< String > fullName = Optional.ofNullable( null );
  System.out.println( "Full Name is set? " + fullName.isPresent() );
  System.out.println( "Full Name: " + fullName.orElseGet( () -> "[none]" ) );
  System.out.println( fullName.map( s -> "Hey " + s + "!" ).orElse( "Hey Stranger!" ) );
 }

résultat de l'opération :

Full Name is set? false
Full Name: [none]
Hey Stranger!

illustrer:

ifPresent()方法当Optional实例的值非空时返回true,否则返回false;
orElseGet()方法当Optional包含非空值时返回该值,否则通过接收的function生成一个默认的;
map()方法转换当前Optional的值,并返回一个新的Optional实例;
orElse()方法与orElseGet方法相似,不同的是orElse()直接返回传入的默认值。

Deuxième exemple :

        Modifiez l'exemple 1 pour générer une instance facultative avec une valeur non nulle.

Optional< String > firstName = Optional.of( "Tom" );
System.out.println( "First Name is set? " + firstName.isPresent() );
System.out.println( "First Name: " + firstName.orElseGet( () -> "[none]" ) );
System.out.println( firstName.map( s -> "Hey " + s + "!" ).orElse( "Hey Stranger!" ) );

résultat de l'opération :

First Name is set? true
First Name: Tom
Hey Tom!

La différence avec l'exemple 1 est clairement visible. Cela simplifie non seulement notre code, mais rend également notre code plus facile à lire.

5.Code source facultatif

        Jetons un coup d'œil au code source de plusieurs méthodes utilisées dans l'exemple :

de

public static <T> Optional<T> of(T value) {
  return new Optional<>(value);
 }

est présent

public boolean isPresent() {
   return value != null;
}

ouElseGet

public T orElseGet(Supplier<? extends T> other) {
    return value != null ? value : other.get();
}

ou sinon

public T orElse(T other) {
    return value != null ? value : other;
}

6. Utilisez Facultatif pour éviter les pointeurs nuls

Dans notre processus de développement quotidien, nous rencontrerons inévitablement des problèmes de pointeur nul. Dans le passé, lorsque des problèmes de pointeur nul survenaient, nous devions généralement déboguer et d'autres méthodes pour finalement localiser l'emplacement spécifique, en particulier lors d'appels entre services système distribués. Le problème est plus difficile à localiser. Après avoir utilisé Facultatif, nous pouvons empaqueter l'objet paramètre reçu. Par exemple, le service de commande doit appeler une interface du service produit et transmettre les informations sur le produit via les paramètres. À ce stade, les paramètres de produit entrants peuvent être transmis directement. Il est nul. À ce stade, la méthode product peut utiliserOptional.of(T) pour envelopper l'objet entrant. Si T est vide, une exception de pointeur nul sera levée directement. Lorsque nous voyons les informations sur l'exception, nous pouvons immédiatement savoir qu'un pointeur nul s'est produit. La raison est que le paramètre T est vide ; ou, lorsque le paramètre entrant est vide, nous pouvons utiliser la méthode Optionnel.orElse() ou Optionnel.orElseGet() pour générer une instance par défaut, puis exécuter opérations ultérieures.

  Regardons un exemple spécifique : il existe une classe Address dans la classe User, une classe Street dans la classe Address et un attribut streetName dans la classe Street. L'exigence actuelle est : obtenir le streetName correspondant en fonction de l'instance User entrante. Si l'utilisateur est nul ou l'adresse est nulle ou la rue est nulle, "rien trouvé" n'est renvoyé, sinon le streetName correspondant est renvoyé.

        1. Voie ordinaire
@Data
public class User {
    private String name;
    private Integer age;
    private Address address;
}

@Data
public class Address {
    private Street street;
}

@Data
public class Street {
    private String streetName;
    private Integer streetNo;}
public String getUserSteetName(User user) {

    if(null != user) {

        Address address = user.getAddress();

        if(null != address) {

            Street street = address.getStreet();

            if(null != street) {
                return street.getStreetName();
            }
        }
    }

    return "nothing found";
}
        2.Utiliser en option

Le problème évident lors de la première mise en œuvre est que le niveau de jugement if est trop profond.Les réutilisations suivantes sont facultatives à réécrire :

@Data
public class User {
    private String name;
    private Integer age;
    private Optional<Address> address = Optional.empty();
}

@Data
public class Address {
    private Optional<Street> street = Optional.empty();
}

@Data
public class Street {
    private String streetName;
    private Integer streetNo;
}


public String getUserSteetName(User user) {

    Optional<User> userOptional = Optional.ofNullable(user);
    final String streetName = userOptional.orElse(new User()).getAddress().orElse(new Address()).getStreet().orElse(new Street()).getStreetName();
    return StringUtils.isEmpty(streetName) ? "nothing found" : streetName;
}

L'utilisation de la méthode orElse() pour donner une valeur par défaut garantit que le problème du pointeur nul ne sera pas signalé et que les exigences peuvent également être respectées.

Je suppose que tu aimes

Origine blog.csdn.net/qq_45443475/article/details/133308753
conseillé
Classement