原文地址:dzone.com/articles/java-optional
Optional
是一种容器对象,可能包含也可能不含非 null
值。如果包含某个值 isPresent()
返回 true
,调用get()
返回该值。1
2Package : java.util
public final class Optional<T> extends Object
以下是 Optional 类中一些有用的方法列表:
1. 创建 Optional 相关方法
方法:Optional.of
、Optional.ofNullable
、Optional.empty()
:1
2
3Optional<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 | Optional<String> nonEmptyOptional = Optional.of("name"); |
ifPresent()
: 如果值存在,则执行代码块
在 Optional
出现前,需要在方法内进行以下 null 检查:1
2
3
4if(data == null){
System.out.println( " data is " + data);
}
// data 是方法内部使用的对象
由于无法确保data在使用前进行了 null 检查,可能会抛出 NullPointerException。
现在,引入Optional
后,可以用 ifPresent
满足类似需求:1
2Optional<String> nonEmptyOptional = Optional.of("name");
nonEmptyOptional.ifPresent( x-> { System.out.println(x.length()); } );
3. 通过 Optional 取值
get()
: 返回值包含在Optional
中返回
1 | Optional<String> nonEmptyOptional = Optional.ofNullable("orignal"); |
orElse()
:如果值不存在,则返回默认值
1 | // Optional 包含 null 时, 使用 orElse 值 |
orElseGet()
:与orElse()
类似,如果Optional
不包含值,用函数作为返回值
1 | // Optional 包含 null 时, 使用 orElse |
orElseThrow()
:与orElseGet()
类似,监测到值为null
时抛出异常
1 | (expected = NullPointerException.class) |
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
13static 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 | public static Optional<Employee> getEmployee(int id,Optional<String> name) { |
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、同步等基于对象标识的操作,调用可能产生无法预测的结果。