为了尽可能的避免空指针异常,jdk8中提出了Optional类。它是一个容器类,代表一个值是否实际存在。
以下是Optional类的常用方法:
1. public static
2. public static
3. public static
4. public boolean isPresent()
5. public T orElse(T other)
6. public T orElseGet(Supplier extends T> other)
7. public Optional map(Function super T, ? extends U> mapper)
8. public Optional flatMap(Function super T, Optional> mapper)
下面我们来逐一分析这些方法如何使用。
创建一个包含t类型对象的Optional实例,如果t为null,Optional.of(null)则会报错: NullPointerException。实际使用时可以这样用:
Optional op1 = Optional.of(new Employee());
System.out.println(op1.get());
源码:
public static Optional of(T value) {
return new Optional<>(value);
}
发现调用了Optional的构造函数。再往下看,
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
调用了Objects工具类(这种java.util包下类似的工具类常见的还有Collections,Arrays等)中的静态方法requireNonNull()
public static T requireNonNull(T obj) {
if (obj == null) //若传入的对象为null,则返回NullPointerException
throw new NullPointerException();
return obj;
}
创建一个空的Optional实例,生成的结果不能直接使用get(),否则报错NoSuchElementException。实际使用时可以这样用:
Optional op2 = Optional.empty();
op2.get(); //这句话会报错: NoSuchElementException
源码:
private static final Optional> EMPTY = new Optional<>();
private Optional() {
this.value = null;
}
public static Optional empty() {
@SuppressWarnings("unchecked")
Optional t = (Optional) EMPTY;
return t;
}
public T get() {
if (value == null) {
throw new NoSuchElementException("No value present");
}
return value;
}
通过调用无参构造函数,返回了一个value值为null的Optional实例,如果对这个实例调用get()方法,那么一定会走入if条件判断语句,抛出NoSuchElementException异常。其中,value就是用来装载外部传入对象的容器!
若value不为null,返回包含value的Optional实例,否则返回空实例。实际使用时可以这样用:
Optional op3 = Optional.ofNullable(
new Employee("Jack", 25, 25000D, Status.BUSY)
);
System.out.println(op3.get());
ofNullable()就是empty()和of()的组合,请看源码:
public static Optional ofNullable(T value) {
return value == null ? empty() : of(value);
}
判断Optional实例中承载的对象是否是null。实际使用时可以这样用:
boolean flag = op3.isPresent(); //op3 是一个Optional实例
System.out.println(flag);
源码一目了然:
public boolean isPresent() {
return value != null; //若存在,则返回true,否则返回false
}
若调用方法的Optional实例承载的对象(value)不为null,则返回该对象,否则返回other。此方法一般用于补充前面的方法,避免NullPointerException的发生,起到保险的作用。实际使用时可以这样用:
//Optional op3 = Optional.of(
// new Employee("Jack", 25, 250000D, Status.BUSY)
//);
Optional op3 = Optional.empty();
Employee employee = op3.orElse(
new Employee("Blue", 26, 30000D, Status.VOCATION)
);
//若op3中的值存在,则返回op3本身的值,否则返回名称为"Blue"的对象
System.out.println(employee);
源码:
public T orElse(T other) {
return value != null ? value : other;
}
与orElse()非常类似,但有时候我们不方便直接返回一个对象,而是需要进行一系列的逻辑处理后才能返回对象,所以jdk8为我们提供了orElseGet(),入参是Supplier供给型接口(如果对Supplier陌生,请点击此链接)。实际使用时可以这样用:
op3.orElseGet(() -> {
System.out.println("逻辑处理语句");
Employee employee= new Employee("Kate", 24, 15000D, Status.RELAX);
return employee;
});
源码:
public T orElseGet(Supplier extends T> other) {
//如果Optional本身承载的value对象不为null,那么直接返回该对象。
//否则,返回自定义的供给型接口返回的对象!
return value != null ? value : other.get();
}
若调用方法的Optional实例承载的对象(value)不为null,则对这个对象进行加工,并返回处理后的Optional,否则返回Optional.Empty()。实际使用时可以这样用:
//返回Employee员工对象中的"员工名称"属性
Optional op4 = op3.map(Employee::getName);
源码:
public Optional map(Function super T, ? extends U> mapper) {
//Function不能为空
Objects.requireNonNull(mapper);
//value必须有值
if (!isPresent())
return empty(); //value为null,则返回空的Optional实例
else {
//之所以使用ofNullable(),因为被函数加工后的value也有可能为null
return Optional.ofNullable(mapper.apply(value));
}
}
与map类似,只不过要求返回值必须是一个Optional实例。实际使用时可以这样用:
Optional op5 = op3.flatMap(
(e) -> Optional.of(e.getName())
);
源码:
public Optional flatMap(Function super T, Optional> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value));
}
}