Maison  >  Article  >  Java  >  Nouvelle API dans Java 8 - Exemples d'utilisation de Facultatif

Nouvelle API dans Java 8 - Exemples d'utilisation de Facultatif

零下一度
零下一度original
2017-05-24 11:40:221955parcourir

Nous savons que Java 8 a ajouté des API très utiles, dont l'une est facultative. Si nous ne l'explorons pas un peu, nous pensons simplement qu'elle peut résoudre avec élégance le problème NullPointException, donc le code commence à. être écrit comme ceci

Optional4c8e0c17c3bd7e0081bb17cc795e1984 user = ......if (user.isPresent()) {return user.getOrders();

} else {return Collections.emptyList();

}

Ensuite, nous devons dire que notre réflexion est toujours au même endroit, mais nous pensons instinctivement que ce n'est qu'un wrapper pour l'instance User. C'est essentiellement la même chose que quoi. nous avons écrit avant

User user = .....if (user != null) {return user.getOrders();

} else {return Collections.emptyList();

}

Il n'y a pas de différence. C'est la bonne posture pour utiliser Java 8 Types facultatifs dont nous allons parler

Pendant les Jeux olympiques de Rio, l'actualité a été répétée à plusieurs reprises. J'ai mentionné qu'il y avait un problème avec le drapeau rouge cinq étoiles, mais je ne pouvais pas le voir, peu importe à quoi je ressemblais. Quel était le problème ? Plus tard, j'ai découvert que la posture de la petite étoile adorant le centre était fausse. , nous ne devons pas prendre pour acquis les choses auxquelles nous sommes habitués, et nous ne ressentirons rien de mal du tout. En d'autres termes, lorsque nous passons à l'Optional de Java 8, nous ne pouvons pas hériter de la façon dont nous traitions null dans le passé, et nous devons maîtriser correctement la nouvelle et correcte posture d'utilisation de Java 8 Facultatif.

Pour parler franchement, lorsque nous utilisons encore les méthodes suivantes Lorsque vous utilisez Facultatif, vous devez commencer à vous vérifier

  1. Lors de l'appel de la méthode isPresent()

  2. Lors de l'appel de la méthode get()

  3. Lorsque le type facultatif est utilisé en tant qu'attribut de classe/instance

  4. Lorsque le type facultatif est utilisé comme paramètre de méthode

isPresent() et obj != null Il y a aucune différence, nos vies sont toujours choquantes étape par étape. L'appel get() sans isPresent() recevra une alerte dans IntelliJ IDEA

Reports calls to java.util.Optional.get() without first checking with a isPresent() call if a value is available. If the Optional does not contain a value, get() will throw an exception.

(l'appel facultatif de .get() n'utilise pas en premier isPresent( ) pour vérifier si la valeur est disponible. Si Facultatif ne contient pas de valeur, get(). Une exception sera levée)

L'utilisation de types facultatifs comme attributs ou paramètres de méthode est fortement déconseillée dans IntelliJ IDEA

Reports any uses of java.util.Optional<T>, java.util.OptionalDouble, java.util.OptionalInt, java.util.OptionalLong or com.google.common.base.Optional as the type 
for
 a field or a parameter. Optional was designed to provide a limited mechanism for library method
 return types where there needed to be a 
clear
 way to represent "no result". Using a field with type java.util.Optional is also problematic if the 
class
 needs to be Serializable, which java.util.Optional is not.

(Utiliser n'importe quel type comme les types facultatifs n'est pas conseillé car champs ou paramètres de méthode Facultatif. Il est uniquement conçu comme une méthode bibliothèque de classes , qui peut indiquer clairement le type de retour lorsqu'il peut n'y avoir aucune valeur. Les types facultatifs ne peuvent pas être sérialisés, et il y aura des problèmes lorsqu'ils sont utilisés comme types de champ)
.

Donc, ce sur quoi nous pouvons vraiment compter dans Facultatif devrait être d'autres méthodes que isPresent() et get() :

public<U> Optional<U> map(Function<? super T, ? extends U> mapper)
public T orElse(T other)
public T orElseGet(Supplier<? extends T> other)
public void ifPresent(Consumer<? super T> consumer)
public Optional<T> filter(Predicate<? super T> predicate)
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X

Je suis quelque peu confiant quant aux méthodes ci-dessus basées sur leur fréquence approximative d'utilisation. Mettons les choses en ordre.

Tout d'abord, je dois mentionner les trois méthodes de construction de Optionnel : Optionnel.of(obj), Optionnel.ofNullable(obj) et explicite Facultatif.empty()

    Optional.of(obj) : 它要求传入的 obj 不能是 null 值的, 否则还没开始进入角色就倒在了 NullPointerException 异常上了.Optional.ofNullable(obj) : 它以一种智能的, 宽容的方式来构造一个 Optional 实例. 来者不拒, 传 null 进到就得到 Optional.empty() , 非 null 就调Optional.of(obj) .

那是不是我们只要用 Optional.ofNullable(obj) 一劳永逸, 以不变应二变的方式来构造 Optional 实例就行了呢? 那也未必, 否则 Optional.of(obj) 何必如此暴露呢, 私有则可?

我本人的观点是:  1. 当我们非常非常的明确将要传给 Optional.of(obj) 的 obj 参数不可能为 null 时, 比如它是一个刚 new 出来的对象( Optional.of(new User(...)) ), 或者是一个非 null 常量时;  2. 当想为 obj 断言不为 null 时, 即我们想在万一 obj 为 null 立即报告 NullPointException 异常, 立即修改, 而不是隐藏空指针异常时, 我们就应该果断的用 Optional.of(obj) 来构造 Optional 实例, 而不让任何不可预计的 null 值有可乘之机隐身于 Optional 中.

现在才开始怎么去使用一个已有的 Optional 实例, 假定我们有一个实例 Optional4c8e0c17c3bd7e0081bb17cc795e1984 user , 下面是几个普遍的, 应避免 if(user.isPresent()) { ... } else { ... } 几中应用方式.

存在即返回, 无则提供默认值

return user.orElse(null);  //而不是 return user.isPresent() ? user.get() : null;return user.orElse(UNKNOWN_USER);

存在即返回, 无则由函数来产生

return user.orElseGet(() -> fetchAUserFromDatabase()); //而不要 return user.isPresent() ? user: fetchAUserFromDatabase();

存在才对它做点什么

user.ifPresent(System.out::println);//而不要下边那样if (user.isPresent()) {
  System.out.println(user.get());
}

map 函数隆重登场

当 user.isPresent() 为真, 获得它关联的 orders , 为假则返回一个空集合时, 我们用上面的 orElse , orElseGet 方法都乏力时, 那原本就是 map 函数的责任, 我们可以这样一行

return user.map(u -> u.getOrders()).orElse(Collections.emptyList())//上面避免了我们类似 Java 8 之前的做法if(user.isPresent()) {  return user.get().getOrders();
} else {  return Collections.emptyList();
}

map 是可能无限级联的, 比如再深一层, 获得用户名的大写形式

return user.map(u -> u.getUsername())
           .map(name -> name.toUpperCase())
           .orElse(null);

这要搁在以前, 每一级调用的展开都需要放一个 null 值的判断

User user = .....if(user != null) {
  String name = user.getUsername();  if(name != null) {    return name.toUpperCase();
  } else {    return null;
  }
} else {  return null;
}

针对这方面 Groovy 提供了一种安全的属性/方法访问操作符 ?.

user?.getUsername()?.toUpperCase();

Swift 也有类似的语法, 只作用在  Optional 的类型上.

用了 isPresent() 处理 NullPointerException 不叫优雅, 有了  orElse, orElseGet 等, 特别是 map 方法才叫优雅.

Quelques autres, filter() transforme les valeurs non qualifiées en empty(), flatMap() est toujours associé à la méthode map(), orElseThrow() renvoie directement quand il y a une valeur, et lance quand il n'y en a pas value L'exception souhaitée est levée.

Résumé en une phrase : lorsque vous utilisez Facultatif, essayez de ne pas appeler directement la méthode Optionnel.get() doit être considérée comme une méthode privée et doit dépendre de. d'autres méthodes comme Optionnel. .util.Facultatif , Ce n'est qu'en lisant le code source que vous pouvez vraiment l'expliquer en toute confiance. Les méthodes facultatives sont essentiellement appelées en interne des jugements isPresent(). Lorsqu'elles sont vraies, la valeur est traitée, et lorsqu'elles sont fausses, rien n'est fait. recommandations】

1.

Partager le code d'instance facultatif de classe nouvellement introduit dans Java 8

2 Analyser l'instance de classe facultative Java 8. Tutoriel

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn