Home > Java > javaTutorial > Correct posture for using Java8 Optional

Correct posture for using Java8 Optional

黄舟
Release: 2017-01-18 15:24:46
Original
1427 people have browsed it

Java Programming Language

Java is an object-oriented programming language that can write cross-platform application software. It is a Java programming language and Java platform launched by Sun Microsystems in May 1995. (That is, the general name of JavaEE(j2ee), JavaME(j2me), JavaSE(j2se)).


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 elegantly solve NullPointException. problem, so the code started to be written like this

Optional<User> user = ……
if (user.isPresent()) {
return user.getOrders();
} else {
return Collections.emptyList();
}
Copy after login

So we have to say that our thinking is still at the same place, but we instinctively think that it is just a wrapper for the User instance, which is different from what we wrote before

User user = …..
if (user != null) {
return user.getOrders();
} else {
return Collections.emptyList();
}
Copy after login

There is essentially no difference. This is the correct posture for using Java 8 Optional types 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 anything wrong no matter how I looked at it, but later I realized that the posture of the little star worshiping the center was wrong. Therefore, we must not take things for granted that we are accustomed to, and we will not feel anything wrong at all. In other words, when When we switch to Java 8 Optional, we cannot inherit the way we used to treat null in the past. We should master the new and correct posture of using Java 8 Optional correctly.

To put it bluntly, when When we are still using Optional in the following ways, we have to start checking ourselves

When calling the isPresent() method

When calling the get() method

Optional type When used as a class/instance attribute

Optional type when used as a method parameter

isPresent() and obj != null There is no difference, our lives are still shocking at every step. Without isPresent( ) to pave the way for get() calls that 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. 
(调用 Optional.get() 前不事先用 isPresent() 检查值是否可用. 假如 Optional 不包含一个值, get() 将会抛出一个异常)
Copy after login

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. (使用任何像 Optional 的类型作为字段或方法参数都是不可取的. Optional 只设计为类库方法的,
  可明确表示可能无值情况下的返回类型. Optional 类型不可被序列化, 用作字段类型会出问题的)
Copy after login

So what we can really rely on in Optional should be other methods besides isPresent() and get():

public Optional map(Function mapper)

public T orElse(T other)

public T orElseGet(Supplier other)

public void ifPresent(Consumer consumer)

public Optional filter(Predicate predicate)

public Optional flatMap(Function> mapper)

public T orElseThrow(Supplier exceptionSupplier) throws .

First I have to mention the three construction methods of Optional: Optional.of(obj), Optional.ofNullable(obj) and explicit Optional.empty()

Optional.of (obj): It requires that the incoming obj cannot be null, otherwise you will get a NullPointerException before entering the role.

Optional.ofNullable(obj): It uses an intelligent method , a tolerant way to construct an Optional instance. All comers are welcome. If null is passed in, Optional.empty() will be obtained. If it is not null, Optional.of(obj) will be called.

Does that mean we only need to use Optional.ofNullable(obj) can be used once and for all, and it is enough to construct the Optional instance in a way that does not change and responds to the second change? That is not necessarily the case, otherwise, why should Optional.of(obj) be exposed like this? It can be private?

My own point of view is: 1. When we are very, very clear that the obj parameter to be passed to Optional.of(obj) cannot be null, for example, it is an object that has just been new (Optional.of(new User(. ..))), or when it is a non-null constant; 2. When we want to assert that obj is not null, that is, if we want to report a NullPointException exception immediately if obj is null, and modify it immediately, instead of hiding the null pointer exception. , we should decisively use Optional.of(obj) to construct Optional instances, without allowing any unpredictable null values ​​to take advantage of the opportunity to hide in Optional.

How to use an Optional now Existing Optional instances, assuming we have an instance Optional user, here are a few common, if(user.isPresent()) { ... } else { ... } application methods that should be avoided.

If it exists, it will be returned. If it does not exist, it will provide a default value.

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

If it exists, it will be returned. If it does not exist, it will be generated by the function.

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

存在才对它做点什么

user.ifPresent(System.out::println);

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

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();
}
Copy after login

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

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

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

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

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

user?.getUsername()?.toUpperCase();
Copy after login

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

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

其他几个, filter() 把不符合条件的值变为 empty(),  flatMap() 总是与 map() 方法成对的,  orElseThrow() 在有值时直接返回, 无值时抛出想要的异常.

一句话小结: 使用 Optional 时尽量不直接调用 Optional.get() 方法, Optional.isPresent() 更应该被视为一个私有方法, 应依赖于其他像 Optional.orElse(), Optional.orElseGet(), Optional.map() 等这样的方法.

最后, 最好的理解 Java 8 Optional 的方法莫过于看它的源代码 java.util.Optional, 阅读了源代码才能真真正正的让你解释起来最有底气, Optional 的方法中基本都是内部调用  isPresent() 判断, 真时处理值, 假时什么也不做.

以上就是使用 Java8 Optional 的正确姿势的内容,更多相关内容请关注PHP中文网(www.php.cn)!


Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template