Java Optional实例介绍

原文地址:dzone.com/articles/java-optional


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

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

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

  

1. 创建 Optional 相关方法

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

1
2
3
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
1
2
Optional<String> nonEmptyOptional = Optional.of("name");
assertTrue(nonEmptyOptional.isPresent());

  

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

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

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

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

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

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

  

3. 通过 Optional 取值

  • get() : 返回值包含在 Optional 中返回
1
2
Optional<String> nonEmptyOptional = Optional.ofNullable("orignal");
String value = nonEmptyOptional.get();

  

  • orElse():如果值不存在,则返回默认值
1
2
3
4
5
6
7
8
// 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 不包含值,用函数作为返回值
1
2
3
4
5
6
7
8
// 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 时抛出异常
1
2
3
4
5
@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

1
2
3
4
5
6
7
8
9
10
11
12
13
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 作为参数,请进行方法重载。

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

1
2
3
4
5
6
7
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。

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

---------------- The End ----------------
0%