Optional容器类
Optional<T> 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念。并且可以避免空指针异常。
常用方法:
1、Optional.of(T t):创建一个 Optional 实例
Optional<Employee> op = Optional.of(new Employee());
System.out.println(op.get());
注意
:使用Optional.of()创建Optional实例的时候不能传入null,否则会报空指针异常,也就是说如果使用Optional.of()出现空指针异常时通常都是传入的实参为null导致的,借助这个特点可以快速锁定空指针异常的位置。
2、Optional.empty():创建一个空的 Optional 实例
Optional<Object> empty = Optional.empty();
System.out.println(empty.get());//报错java.util.NoSuchElementException: No value present
一旦Optional容器empty时再调用其get(),就会报NoSuchElementException异常
3、Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例,该方法是of()和empty()的组合,如果为empty时调用get()会报异常NoSuchElementException
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
4、isPresent():判断容器中是否包含值,用此方法可避免NoSuchElementException异常
Optional<Object> ofNullable = Optional.ofNullable(null);
if (ofNullable.isPresent())//若有值则执行if逻辑
System.out.println(ofNullable.get());
5、orElse(T t):如果调用对象包含值,返回该值,否则返回t,此方法也可以避免出现空指针异常
Optional<Employee> op = Optional.ofNullable(null);
Employee orElse = op.orElse(new Employee("zhangsan"));
System.out.println(orElse);
6、orElseGet(Supplier s):如果调用对象包含值,返回该值,否则返回 s 获取的值,与orElse不同的是,这里返回的值是在函数中返回的,可以有更多的逻辑判断具体返回哪个值
Optional<Employee> op = Optional.ofNullable(null);
Employee orElseGet = op.orElseGet(Employee::new);//可以通过Supplier写各种逻辑
System.out.println(orElseGet);
7、map(Function f):如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty(),通过map将原容器中的类映射为新容器中的类型
Optional<Employee> op = Optional.of(new Employee("张三"));
Optional<String> map = op.map(e -> e.getName());//通过map将原容器中的类映射为新容器中的类型
System.out.println(map.get());
8、flatMap(Function mapper):与 map 类似,但要求Function 的返回值必须是Optional类型,可实现流数据的扁平化等
Optional<Employee> op = Optional.of(new Employee("张三"));
Optional<String> flatMap = op.flatMap((e) -> Optional.of(e.getName()));
System.out.println(flatMap.get());
示例:
①Godness
public class Godness {
private String name;
public Godness() {
}
public Godness(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Godness [name=" + name + "]";
}
}
②Man:将其所有可能为null属性都包装成Optional,且需要初始化值Optional.empty(),否则还会出现空指针
public class Man {
private Optional<Godness> godness = Optional.empty();// 这里一定要初始化
public Man() {
}
public Man(Optional<Godness> godness) {
this.godness = godness;
}
public Optional<Godness> getGodness() {
return godness;
}
public void setGodness(Optional<Godness> godness) {
this.godness = godness;
}
@Override
public String toString() {
return "Man [godness=" + godness + "]";
}
}
③方法的封装和调用
public class TestOptional {
@Test
public void test() {
Optional<Man> man = Optional.ofNullable(null);
String godnessName = getGodnessName(man);//传入的值需包装成Optional
System.out.println(godnessName);
}
public static String getGodnessName(Optional<Man> man) {
return man.orElse(new Man())//为null则新建默认
.getGodness()//获取到的是Optional对象,由于在Man中初始化了值,不可能为null
.orElse(new Godness("小龙女"))//null时初始化
.getName();
}
}
从编码上可以看到,使用Optional虽然可以避免空指针异常,但是这种编码方式远不够优雅,Optional容器类是不是有些过度设计尚未可知。