查看原文
其他

Java Optional 实例介绍

ImportNew ImportNew 2019-12-01

(给ImportNew加星标,提高Java技能)

编译:ImportNew/唐尤华

dzone.com/articles/java-optional


Optional 是一种容器对象,可能包含也可能不含非 null 值。如果包含某个值 isPresent() 返回 true,调用get()返回该值。


Package : java.util
public final class Optional<T> extends Object


以下是 Optional 类中一些有用的方法列表:


1. 创建 Optional 相关方法


方法:Optional.ofOptional.ofNullableOptional.empty()


Optional<String> emptyOptional = Optional.empty();
Optional<String> nonEmptyOptional = Optional.of("name"); // 对 null 无效
Optional<String> nonEmptyOptional = Optional.ofNullable(null); // 支持 null


2. 检查 Optional 值


方法:Optional.isPresent()Optional.ifPresent()


  • 如果 Optional有值,isPresent() 返回 true


Optional<String> nonEmptyOptional = Optional.of("name");
assertTrue(nonEmptyOptional.isPresent());


  • ifPresent() = 如果值存在,则执行代码块


Optional 出现前,需要在方法内进行以下 null 检查。


if(data == null){
System.out.println( " data is " + data);
}
// data 是方法内部使用的对象


由于无法确保data在使用前进行了 null 检查,可能会抛出 NullPointerException


现在,引入Optional 后,可以用 ifPresent满足类似需求。


Optional<String> nonEmptyOptional = Optional.of("name");
nonEmptyOptional.ifPresent( x-> { System.out.println(x.length()); } );


3. 通过 Optional 取值


  • get() = 返回值包含在 Optional 中返回

Optional<String> nonEmptyOptional = Optional.ofNullable("orignal");
String value = nonEmptyOptional.get();


  • orElse() = 如果值不存在,则返回默认值


// Optional 包含 null 时, 使用 orElse 值
Optional<String> emptyOptional = Optional.ofNullable(null);
String value = emptyOptional.orElse("default Value");
assertEquals("default Value", value);
// Optional 不包含 null 时, 不使用 orElse 值
Optional<String> nonEmptyOptional = Optional.ofNullable("orginal");
String value1 = nonEmptyOptional.orElse("default Value");
assertEquals("orginal", value1);


  • orElseGet() = 与 orElse() 类似,如果 Optional 不包含值,用函数作为返回值

// Optional 包含 null 时, 使用 orElse
Optional<String> emptyOptional = Optional.ofNullable(null);
String value = emptyOptional.orElseGet(()->"default value");
assertEquals("default value", value);
// Optional 不包含 null 时, 不使用 orElse
Optional<String> nonEmptyOptional = Optional.ofNullable("orginal");
String value1 = nonEmptyOptional.orElseGet(()->"default value");
assertEquals("orginal", value1);


  • orElseThrow() = 与 orElseGet() 类似,监测到值为 null 时抛出异常


@Test(expected = NullPointerException.class)
public void OrElseThrowCheck() {
String nullName = null;
String value = Optional.ofNullable(nullName).orElseThrow(NullPointerException::new);
}


4. Optional 用法


  • 使用 Optional 作为返回值


Optional 的常见用法是作为方法返回值。定义方法时,可以根据实现逻辑返回 null 或对象。返回 Optional 对象是一种很好的方法,开发人员知道返回值可能是 null,迫使他们合理地处理返回的对象。Optional 的优点在于,能够引导开发者进行恰当的检查,从而避免 NullPointerException。


下面的例子定义了 Optional<Employee>getEmployeeWithId(int id) 方法,返回值类型为 Optional<Employee>。调用者需要通过 Optional 方法得到返回值。执行过程中可以避免 NullPointerExceptions。


static List<Employee> employess = new ArrayList<>();
public static void main(String[] args) throws EmployeeNotFoundException {
employess.add(new Employee("emp1", 1, 1000));
employess.add(new Employee("emp2", 2, 2000));
employess.add(new Employee("emp1", 3, 3000));
Optional<Employee> employee = getEmployeeWithId(1);
Employee e = employee.orElseThrow(() -> new EmployeeNotFoundException("emp not found"));
System.out.println(e);
}
public static Optional<Employee> getEmployeeWithId(int id) {
Optional<Employee> employee = employess.stream().filter(e -> (e.getId() == id)).findFirst();
return employee;
}


  • 使用 Optional 作为方法参数


不推荐使用Optional 作为方法参数。假设一个方法包含两个参数:一个类型是 Optional,另一个类型是非 Optional。背后的逻辑是,第一个参数值可能为 null


这种情况,不要使用 Optional 作为参数,请进行方法重载


上面的例子最好定义重载方法,只接受一个参数。

public static Optional<Employee> getEmployee(int id,Optional<String> name) {
...
return employee;
}
// 更好的方法: 重载方法
public static Optional<Employee> getEmployee(int id,String name)
public static Optional<Employee> getEmployee(int id)


5. Java 各版本新增的 Optional 方法列表


  • Java 9

  • or():如果值存在,返回包含该值的 Optional 对象;否则,返回 or() 函数生成的 Optional 对象。

  • ifPresentOrElse(Consumer<? super T>action, Runnable emptyAction):如果值存在,使用该值执行指定调用,否则使用空值执行调用。

  • stream():如果值存在,返回该值的顺序流(Stream);否则返回空流。

  • Java 10

  • orElseThrow():如果值存在,返回该值;否则抛出 NoSuchElementException。注意:与 Java 8 不同,不接受任何参数。

  • Java 11

  • isEmpty():如果值不存在,返回 true;否则返回 false。


6. 完整代码


源代码请参考下面 Git 链接:


  • 源代码:方法 “getEmployeeWithId” 返回 Optional<Employee>

  • 源代码:Optional 方法测试用例


说明Optional 是基于值的类,应当避免对Optional 对象调用像引用相等性(==)、HashCode、同步等基于对象标识的操作,调用可能产生无法预测的结果。


7. 参考文档


以下是不同 Java 版本的参考文档:



推荐阅读

(点击标题可跳转阅读)

Java 8 如何正确使用 Optional

使用 Java8 Optional 的正确姿势

不论喜欢还是讨厌,Java 都在不断进化


看完本文有收获?请转发分享给更多人

关注「ImportNew」,提升Java技能

好文章,我在看❤️

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存