Java8 Optional的使用

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类构造方式

  1. 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());
 });
  1. 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());
});
  1. Optional.empty()
    显示的创建一个空的Optional对象
Optional<User> op = Optional.empty();
op.ifPresent(u->{
    //不执行
    System.out.println(u.getName());
});

Optional类其他方法

  1. 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);
  1. orElseGet(Supplier 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()方法。

  1. orElseThrow(Supplier exceptionSupplier)
    放值存在时返回值,值不存在则抛出参数异常。
User lisi = op.orElseThrow(() -> new  NullPointerException());
System.out.println(lisi);
  1. ifPresent(Consumer 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());
}
  1. isPresent()
    判断对象值是否存在,返回boolean值
Optional<User> op = Optional.empty();
boolean flag = op.isPresent()
//打印false
System.out.println(flag);
  1. map()
    参数:Function 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);
}
  1. 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);
  1. filter()
    参数:Predicate 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);

你可能感兴趣的:(java)