Optional简介
Optional类是java8新增的类,主要是用来解决空指针异常(NullPointerException)。Optional类在函数式编程规范中具有重要意义。Optional方法可以避免频繁的判空操作。
例如:
public void function(User u){
if(u!=null){
Adder adder = u.getAdder();
if(adder!=null){
Area area = adder.getArea();
if(area!=null){
String name = area.getName();
if(name!=null){
System.out.println(name.toUpperCase());
}
}
}
}
}
如果不这样一层层的判空,直接执行,则很有可能抛出空指针异常:
System.out.println(u.getAdder().getArea.getName().toUpperCase());
如果我们使用了Optional类,则很方便的排除了频繁的判空操作:
Optional op = Optional.ofNullable(u);
String name = op.map(User::getAdder)
.map(Adder::getArea)
.map(Area::getName)
.map(String::toUpperCase)
.orElse("");
System.out.println(name);
注意:
- isPresent()方法与obj!=null并无区别
- Optional类不应该用在类的属性和方法参数上(Optional类型不可被序列化)
- 使用Optional应该使用此类提供的各种方法来判空,而不是直接使用isPresent()和get()方法,这样与平时的!=null并没有本质的优化和区别
Optional类使用
Optional类构造方式
- Optional.of(obj)
传入的obj值不能为null值,否则抛出异常NullPointerException。
User user = new User("zhangsan",23);
Optional<User> op = Optional.of(user);
op.ifPresent(u->{
//执行打印
System.out.println(u.getName());
});
- Optional.ofNullable(obj)
传入的值不明确是否为null (obj可能为null,可能不为)。源代码是判断了obj是否为null来分别调用Optional.empty()和Optional.of(obj)方法来实现。
User user = null;
Optional<User> op = Optional.ofNullable(user);
op.ifPresent(u->{
//不执行
System.out.println(u.getName());
});
- Optional.empty()
显示的创建一个空的Optional对象
Optional<User> op = Optional.empty();
op.ifPresent(u->{
//不执行
System.out.println(u.getName());
});
Optional类其他方法
- orElse(obj)
存在则直接返回,不存在则返回提供的默认值;
User user1 = null;
User user2 = new User("lisi",24);
Optional<User> op = Optional.ofNullable(user1);
//如果op对象值为空则返回user2,否则返回原值
User user = op.orElse(user2);
System.out.println(user);
- orElseGet(Supplier<? extends T> other)
存在则直接返回,不存在则由函数产生
User user1 = null;
Optional<User> op = Optional.ofNullable(user1);
//op有值则直接返回值,否则执行函数生成返回
User user = op.orElseGet(()-> new User("lisi",25));
System.out.println(user);
注意:如果代码
User user = op.orElse(createObj());
User user = op.orElseGet(createObj());
public User createObj(){
return new User();
}
当op为empty时,都会执行createObj()方法。当op不为empty时,orElse还是会执行createObj()方法,造成内存开销。而orElseGet()则不会执行createObj()方法。
- orElseThrow(Supplier<? extends X> exceptionSupplier)
放值存在时返回值,值不存在则抛出参数异常。
User lisi = op.orElseThrow(() -> new NullPointerException());
System.out.println(lisi);
- ifPresent(Consumer<? super T> consumer)
当值存在则执行函数式方法
User user = new User("zhangsan",23);
Optional<User> op = Optional.of(user);
op.ifPresent(u->{
//执行打印
System.out.println(u.getName());
});
不要像以前那样的方式来使用:
if (op.isPresent()) {
System.out.println(op.get());
}
- isPresent()
判断对象值是否存在,返回boolean值
Optional<User> op = Optional.empty();
boolean flag = op.isPresent()
//打印false
System.out.println(flag);
- map()
参数:Function<? super T, ? extends U> mapper
返回值:Optional
Optional对象的映射,可以级联返回Optional对象供连续调用。
例如:需要获取user的姓名,并将姓名转换为大写打印,如果不存在则打印不存在
原始写法
//原始写法,不得不一层一层的执行判空操作
public void function(User user){
if(user!=null){
String name = user.getName();
if(name!=null){
System.out.println(name.toUpperCase());
}else{
System.out.println("不存在");
}
}else{
System.out.println("不存在");
}
}
Optional.map() 方法
//使用了map方法,级联的调用,精简代码
public void function(User user){
String name = op.map(u -> u.getName())
.map(n -> n.toUpperCase())
.orElse("不存在");
System.out.println(name);
}
- flatMap()
flatMa()方法与map类似,不同的是,map的参数函数式方法返回的类型是Optional,而flatMap的参数函数式方法赶回的类型是拆包装值。
public class User {
private String name;
private Integer age;
private Integer sex;
public Optional<Integer> getSex(){
return Optional.ofNullable(sex);
}
}
//flatMap的参数返回值必须为Optional类型
Integer sex = op.flatMap(User::getSex).orElse(-1);
System.out.println(sex);
- filter()
参数:Predicate<? super T> predicate
返回值:Optional
filter方式可以通过执行参数方法来过滤值,不通过则返回empty对象,通过则返回原对象。
Optional<User> op = Optional.of(new User("李四",20));
//使用filter过滤是否是张三,再用map映射返回
String s = op.filter(u -> u.getName().equals("张三"))
.map(User::getName)
.orElse("不存在");
//打印不存在
System.out.println(s);