1. Optional的简介
Optional是Java 8新增的一个类型,表示一个值可以是null或者一个非null的值。在Java 8中,Optional被广泛地用于解决null相关的异常问题。虽然Optional在Java 8中已经有了较大的用武之地,但在Java 9中,Optional得到了进一步的扩展和完善。
2. Optional.or()方法的介绍
Optional中常用的方法包括get()、isPresent()、orElse()、orElseGet()、orElseThrow()等,这些方法都旨在帮助我们更好地处理null值,从而让代码更加优雅、易读。
在Java 9中,Optional新增了一个方法:or()。通过查看源码,我们可以得到or()方法的签名:
public Optional or(Supplier extends Optional extends T>> supplier) {
Objects.requireNonNull(supplier);
return isPresent() ? this : supplier.get();
}
or()方法接收一个Supplier类型的参数,Supplier的get()方法返回一个Optional类型的值。or()方法的作用就是:如果Optional对象的值存在,直接返回该对象,否则返回supplier.get()返回的Optional对象。
3. or()方法的使用场景
在实际开发中,我们常常会遇到这样的场景:如果对象为null,则尝试从其他地方获取数据。在这种场景下,我们可以使用or()方法,让代码更加优雅、易读。
3.1 一个简单的场景
假设我们有一个方法,用于获取一个人的姓名。如果这个人的姓名为null,那么我们就从其他的地方获取他的姓名。一个不优雅的实现代码如下:
public String getName(Person person) {
if(person.getName() == null){
String name = getNameFromOtherMethod(person.getId());
if(name == null){
return "unknown";
}
return name;
}
return person.getName();
}
可以看到,上述代码中嵌套了两个if语句,而使用Optional的or()方法可以让代码更加简洁:
public String getName(Person person) {
return Optional.ofNullable(person.getName())
.or(() -> Optional.ofNullable(getNameFromOtherMethod(person.getId())))
.orElse("unknown");
}
该方法的工作流程如下:
如果person.getName()不为null,直接返回该值;
如果person.getName()为null,则执行Supplier的get()方法,尝试获取一个Optional值;
如果Supplier的get()方法返回的Optional值不为null,则返回该值;
如果Supplier的get()方法返回的Optional值为null或Supplier本身为null,则返回"unknown"。
3.2 一个稍微复杂的场景
假设我们有一个系统,用于管理用户。在用户注册时,我们需要对用户的密码进行加密,并保存到数据库中。
为了保证用户密码的安全性,我们采用SHA-512算法进行加密:
public String encrypt(String password){
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-512");
messageDigest.update(password.getBytes());
byte[] bytes = messageDigest.digest();
StringBuilder stringBuilder = new StringBuilder();
for (byte b : bytes) {
stringBuilder.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
}
return stringBuilder.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
我们的用户类如下:
public class User {
private String username;
private String password;
// getter和setter方法省略
}
在用户注册时,我们需要对用户的密码进行加密。但是,在某些情况下,用户可能没有设置密码。在这种情况下,我们需要生成一个随机的密码,然后再对其进行加密,并将加密后的值保存到数据库中。
为了实现这个功能,提高代码的可读性,我们可以使用Optional的or()方法。
public boolean register(User user){
return Optional.ofNullable(user.getPassword())
.or(() -> Optional.ofNullable(generateRandomPassword()))
.map(this::encrypt)
.map(password -> {
user.setPassword(password);
return true;
}).orElse(false);
}
// 生成一个随机的密码,长度为10
private String generateRandomPassword() {
String randomString = UUID.randomUUID().toString().replaceAll("-", "");
return randomString.substring(0, Math.min(10, randomString.length()));
}
3.3 or()方法的点睛之笔
在上面两个例子中,我们已经看到了or()方法在实际开发中的应用场景。但是,有时候我们可能需要针对不同的情况返回不同的值。在这种情况下,or()方法不能满足我们的需求,因为它只能返回一个Optional类型的值。
为了克服这个问题,我们可以借鉴Java 8中Stream的思路,采用map()方法+orElse()方法实现我们的目标。下面是一个例子:
public String demo(){
return Optional.ofNullable(getValue())
.map(this::processValue)
.orElseGet(this::getValueFromOtherSource);
}
private String getValue(){
// 从数据库中获取值
return null;
}
private String processValue(String value){
// 处理值,如果不符合条件,返回null
return value;
}
private String getValueFromOtherSource(){
// 从其他地方获取值
return "default value";
}
可以看到,我们先使用map()方法对Optional对象的值进行处理,然后通过orElseGet()方法返回一个默认值。
4. 总结
Optional是一个非常实用的类,可以帮助我们能够更好地处理null值。在Java 9中,Optional新增了or()方法,可以帮助我们更好地解决一些常见的编程问题。
通过使用or()方法,我们可以优化代码,提高代码的可读性和可维护性。在特定的场景下,我们可以借鉴Stream中的思路,使用map()方法+orElse()方法实现更为灵活的逻辑。