We know that Java 8 has added some very useful APIs, one of which is Optional. If you don’t explore it a little bit, you just lightly think that it can solve the NullPointException problem elegantly, so the code starts to be written like this
Optional<User> user = ......if (user.isPresent()) {return user.getOrders(); } else {return Collections.emptyList(); }
Then we have to say that our thinking is still on the same spot, but we instinctively think that it is just a wrapper for the User instance. This is essentially the same as what we wrote before
User user = .....if (user != null) {return user.getOrders(); } else {return Collections.emptyList(); }
. This is essentially the same. This is the correct posture for using the Java 8 Optional type that we are going to talk about.
During the Rio Olympics, the news repeatedly mentioned that there was a problem with the five-star red flag, but I couldn’t see any problem no matter how I looked at it. Later, The trick is that the posture of the little star worshiping the center is wrong. Therefore, we must not take things we are accustomed to for granted, and we will not feel anything wrong at all. In other words, when we switch to Java 8's Optional, we cannot inherit properties. We should master the new and correct attitude of using Java 8 Optional in the same way we used to treat null in the past.
To put it bluntly, when we are still using Optional in the following ways, You have to start checking yourself
When calling the isPresent() method
When calling the get() method
When the Optional type is used as a class/instance attribute
When the Optional type is used as a method parameter
isPresent() and obj != null There is no difference, our lives are still shocking step by step. And get() calls without isPresent() will receive warnings in 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.
(calling Optional.get() has not been done before) Check beforehand whether the value is available using isPresent(). If Optional does not contain a value, get()
An exception will be thrown)
Using Optional types as attributes or method parameters is strongly not recommended in 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.
(Use any type like Optional Not available as field or method parameters. Optional
It is only designed as a class library method, which can clearly indicate the return type when there may be no value. The Optional type cannot be serialized, and it will cause problems when used as a field type)
So what we can really rely on in Optional should be other methods besides isPresent() and 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
I am somewhat confident that I have ranked the above methods according to their approximate frequency of use. To start with.
First I have to mention the three construction methods of Optional: Optional.of(obj), Optional.ofNullable(obj) and explicit Optional.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 实例, 假定我们有一个实例 Optional
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()); }
当 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 方法才叫优雅.
Others, filter() changes the value that does not meet the conditions into empty(), flatMap() is always paired with the map() method, orElseThrow() returns directly when there is a value, and throws when there is no value The desired exception is thrown.
One sentence summary: When using Optional, try not to call the Optional.get() method directly. Optional.isPresent() should be regarded as a private method and should depend on other methods like Optional. .orElse(), Optional.orElseGet(), Optional.map() and other such methods.
Finally, the best way to understand Java 8 Optional is to look at its source code java.util.Optional , Only by reading the source code can you truly be confident in explaining it. Optional methods are basically internally called isPresent() to judge. When true, the value is processed, and when false, nothing is done.
【 Related recommendations】
1. Share the newly introduced class Optional instance code in Java 8
2. Analyze Java 8 Optional class instance Tutorial
The above is the detailed content of New API in Java 8--Usage examples of Optional. For more information, please follow other related articles on the PHP Chinese website!