@Test publicvoidwhenCheckIfPresent_thenOk(){ User user = new User("john@gmail.com", "1234"); Optional<User> opt = Optional.ofNullable(user); Assert.assertTrue(opt.isPresent());
@Test publicvoidwhenEmptyValue_thenReturnDefault(){ User user = null; User user2 = new User("anna@gmail.com", "1234"); User result = Optional.ofNullable(user).orElse(user2);
这里 user 对象是空的,所以返回了作为默认值的 user2。其中 orElse 底层做了如下处理:
1 2 3
public T orElse(T other){ return value != null ? value : other; }
如果对象的初始值不是 null,那么默认值会被忽略:
1 2 3 4 5 6 7 8
@Test publicvoidwhenValueNotNull_thenIgnoreDefault(){ User user = new User("john@gmail.com","1234"); User user2 = new User("anna@gmail.com", "1234"); User result = Optional.ofNullable(user).orElse(user2); // user
第二个同类型的 API 是 orElseGet() —— 其行为略有不同。这个方法会在有值的时候返回值,如果没有值,它会执行作为参数传入的 Supplier(供应者) 函数式接口,并将返回其执行结果:
1
User result = Optional.ofNullable(user).orElseGet( () -> user2);
orElse() 和 orElseGet() 的不同之处
乍一看,这两种方法似乎起着同样的作用。然而事实并非如此。我们创建一些示例来突出二者行为上的异同。
我们先来看看对象为空时他们的行为:
1 2 3 4 5 6 7 8 9 10 11
@Test publicvoidgivenEmptyValue_whenCompare_thenOk(){ User user = null; User result = Optional.ofNullable(user).orElse(createNewUser("orElse")); User result2 = Optional.ofNullable(user).orElseGet(() -> createNewUser("orElseGet")); }
private User createNewUser(String method){ System.out.println("Creating New User with " + method); returnnew User("extra@gmail.com", "1234"); }
上面的代码中,两种方法都调用了 createNewUser() 方法,这个方法会记录一个消息并返回 User 对象。
代码输出如下:
1 2
Creating New User with orElse Creating New User with orElseGet
由此可见,当对象为空而返回默认对象时,行为并无差异。
我们接下来看一个类似的示例,但这里 Optional 不为空:
1 2 3 4 5 6
@Test publicvoidgivenPresentValue_whenCompare_thenOk(){ User user = new User("john@gmail.com", "1234"); User result = Optional.ofNullable(user).orElse(createNewUser("orElse")); User result2 = Optional.ofNullable(user).orElseGet(() -> createNewUser("orElseGet")); }
这次的输出:
1
Creating New User with orElse
这个示例中,两个 Optional 对象都包含非空值,两个方法都会返回对应的非空值。不过,orElse() 方法仍然创建了 User 对象。与之相反,orElseGet() 方法不创建 User 对象。
在执行较密集的调用时,比如调用 Web 服务或数据查询,这个差异会对性能产生重大影响。
2.2 返回异常
除了 orElse() 和 orElseGet() 方法,Optional 还定义了 orElseThrow() API —— 它会在对象为空的时候抛出异常,而不是返回备选的值:
1 2 3 4 5 6
@Test publicvoidwhenThrowException_thenOk(){ User user = null; User result = Optional.ofNullable(user) .orElseThrow(() -> new IllegalArgumentException()); }
@Test publicvoidwhenFlatMap_thenOk(){ User user = new User("anna@gmail.com", "1234"); user.setPosition("Developer"); String position = Optional.ofNullable(user) .flatMap(u -> u.getPosition()).orElse("default");
@Test publicvoidwhenFilter_thenOk(){ User user = new User("anna@gmail.com", "1234"); Optional<User> result = Optional.ofNullable(user) .filter(u -> u.getEmail() != null && u.getEmail().contains("@"));
@Test publicvoidwhenEmptyStream_thenReturnDefaultOptional(){ List<User> users = new ArrayList<>(); User user = users.stream().findFirst().orElse(new User("default", "1234"));