JDK1.8新特性值Optional

在我们的开发中,NullPointerException可谓是随时随处可见,为了避免空指针异常,我们常常需要进行一些防御式的检查,所以在代码中常常可见if(obj != null) 这样的判断。幸好在JDK1.8中,java为我们提供了一个Optional类,Optional类能让我们省掉繁琐的非空的判断。

下面先说一下Optional中为我们提供的方法

of  

把指定的值封装为Optional对象,如果指定的值为null,则抛出NullPointerException

//创建一个值为张三的String类型的Optional
Optional<String> ofOptional = Optional.of("张三");
//如果我们用of方法创建Optional对象时,所传入的值为null,则抛出NullPointerException如下图所示
Optional<String> nullOptional = Optional.of(null);


empty   

创建一个空的Optional对象

//创建一个空的String类型的Optional对象
Optional<String> emptyOptional = Optional.empty();

ofNullable

把指定的值封装为Optional对象,如果指定的值为null,则创建一个空的Optional对象

//为指定的值创建Optional对象,不管所传入的值为null不为null,创建的时候都不会报错
Optional<String> nullOptional = Optional.ofNullable(null);
Optional<String> nullOptional2 = Optional.ofNullable("lisi");

get

如果我们创建的Optional对象中有值存在则返回此值,如果没有值存在,则会抛出
NoSuchElementException异常。

Optional<String> stringOptional = Optional.of("张三");
System.out.println(stringOptional.get());

Optional<String> emptyOptional = Optional.empty();
System.out.println(emptyOptional.get());


orElse

如果创建的Optional中有值存在,则返回此值,否则返回一个默认值

Optional<String> stringOptional = Optional.of("张三");
System.out.println(stringOptional.orElse("zhangsan"));

Optional<String> emptyOptional = Optional.empty();
System.out.println(emptyOptional.orElse("李四"));


orElseGet

如果创建的Optional中有值存在,则返回此值,否则返回一个由Supplier接口生成的值

Optional<String> stringOptional = Optional.of("张三");
System.out.println(stringOptional.orElseGet(() -> "zhangsan"));

Optional<String> emptyOptional = Optional.empty();
System.out.println(emptyOptional.orElseGet(() -> "orElseGet"));


 orElseThrow

如果创建的Optional中有值存在,则返回此值,否则抛出一个由指定的Supplier接口生成的异常

Optional<String> stringOptional = Optional.of("张三");
System.out.println(stringOptional.orElseThrow(CustomException::new));

Optional<String> emptyOptional = Optional.empty();
System.out.println(emptyOptional.orElseThrow(CustomException::new));

private static class CustomException extends RuntimeException {
   private static final long serialVersionUID = -4399699891687593264L;

   public CustomException() {
       super("自定义异常");
   }

   public CustomException(String message) {
      super(message);
   }
  }


 filter

如果创建的Optional中的值满足filter中的条件,则返回包含该值的Optional对象,否则返回一个空的Optional对象

Optional<String> stringOptional = Optional.of("zhangsan");
System.out.println(stringOptional.filter(e -> e.length() > 5).orElse("王五"));
stringOptional = Optional.empty();
System.out.println(stringOptional.filter(e -> e.length() > 5).orElse("lisi"));

注意Optional中的filter方法和Stream中的filter方法是有点不一样的,Stream中的filter方法是对一堆元素进行过滤,而Optional中的filter方法只是对一个元素进行过滤,可以把Optional看成是最多只包含一个元素的Stream。 


map

如果创建的Optional中的值存在,对该值执行提供的Function函数调用

//map方法执行传入的lambda表达式参数对Optional实例的值进行修改,修改后的返回值仍然是一个Optional对象
Optional<String> stringOptional = Optional.of("zhangsan");
System.out.println(stringOptional.map(e -> e.toUpperCase()).orElse("失败"));

stringOptional = Optional.empty();
System.out.println(stringOptional.map(e -> e.toUpperCase()).orElse("失败"));


flagMap

如果创建的Optional中的值存在,就对该值执行提供的Function函数调用,返回一个Optional类型的值,否则就返回一个空的Optional对象.flatMap与map(Funtion)方法类似,区别在于flatMap中的mapper函数返回值必须是Optional,map方法的mapper函数返回值可以是任何类型T。调用结束时,flatMap不会对结果用Optional封装。

   //map方法中的lambda表达式返回值可以是任意类型,在map函数返回之前会包装为Optional。
   //但flatMap方法中的lambda表达式返回值必须是Optionl实例
   Optional<String> stringOptional = Optional.of("zhangsan");
   System.out.println(stringOptional.flatMap(e -> Optional.of("lisi")).orElse("失败"));

   Optional<Object> objectOptional = Optional.empty();
   System.out.println(objectOptional.flatMap(e -> Optional.empty()).orElse("失败"));


isPresent

如果创建的Optional中的值存在,返回true,否则返回false


ifPresent 

如果创建的Optional中的值存在,则执行该方法的调用,否则什么也不做       

//ifPresent方法的参数是一个Consumer的实现类,Consumer类包含一个抽象方法,该抽象方法对传入的值进行处理,只处理没有返回值。
Optional<String> stringOptional = Optional.of("zhangsan");
stringOptional.ifPresent(e-> System.out.println("我被处理了。。。"+e));


实战场景

场景1

在service层中查询一个对象,返回之后判断是否为空并做处理

//查询一个对象
Member member = memberService.selectByIdNo(request.getCertificateNo());
//使用ofNullable加orElseThrow做判断和操作
Optional.ofNullable(member).orElseThrow(() -> new ServiceException("没有查询的相关数据"));

场景2

我们可以在dao接口层中定义返回值时就加上Optional 例如:我使用的是jpa,其他也同理

public interface LocationRepository extends JpaRepository<Location, String> {
Optional<Location> findLocationById(String id);
}

然在是Service中

c TerminalVO findById(String id) {
//这个方法在dao层也是用了Optional包装了
        Optional<Terminal> terminalOptional = terminalRepository.findById(id);
        //直接使用isPresent()判断是否为空
        if (terminalOptional.isPresent()) {
        //使用get()方法获取对象值
            Terminal terminal = terminalOptional.get();
            //在实战中,我们已经免去了用set去赋值的繁琐,直接用BeanCopy去赋值
            TerminalVO terminalVO = BeanCopyUtils.copyBean(terminal, TerminalVO.class);
            //调用dao层方法返回包装后的对象
            Optional<Location> location = locationRepository.findLocationById(terminal.getLocationId());
            if (location.isPresent()) {
                terminalVO.setFullName(location.get().getFullName());
            }
            return terminalVO;
        }
        //不要忘记抛出异常
        throw new ServiceException("该终端不存在");
    }

Optional真么好用,真的可以完全替代if判断吗?

我想这肯定是大家使用完之后Optional之后可能会产生的想法,答案是否定的

举一个最简单的例子:

如果我只想判断对象的某一个变量是否为空并且做出判断呢?

Person person=new Person();
person.setName("");
persion.setAge(2);
//普通判断
if(StringUtils.isNotBlank(person.getName())){
  //名称不为空执行代码块
}
//使用Optional做判断
Optional.ofNullable(person).map(p -> p.getName()).orElse("name为空");

我觉得这个例子就能很好的说明这个问题,只是一个很简单判断,如果用了Optional我们还需要考虑包装值,考虑代码书写,考虑方法调用,虽然只有一行,但是可读性并不好,如果别的程序员去读,我觉得肯定没有if看的明显

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值