Optional方法和实战讲解

1 篇文章 0 订阅
1 篇文章 0 订阅

什么是Optional

在Java中,Optional是一个用于解决空指针异常的类。它是一个容器对象,可以包含或者不包含非空值。Optional类的设计思想是将可能为空的值封装在一个对象中,并提供一系列的方法来对这个值进行操作,同时避免了空指针异常的发生。

使用Optional可以代替使用null来表示一个值不存在的情况,这样可以提供更加清晰和安全的代码。Optional类提供了许多方法来处理包含或者不包含值的情况,例如:

  • of(T value):创建一个包含指定值的Optional对象,如果指定值为null,则抛出NullPointerException异常。
  • ofNullable(T value):创建一个包含指定值的Optional对象,如果指定值为null,则创建一个空的Optional对象。
  • isEmpty():判断Optional对象中是否不包含值。
  • isPresent():判断Optional对象中是否包含值。
  • get():获取Optional对象中的值,如果Optional为空,则抛出NoSuchElementException异常。
  • orElse(T other):获取Optional对象中的值,如果Optional为空,则返回指定的默认值。
  • orElseGet(Supplier<? extends T> other):获取Optional对象中的值,如果Optional为空,则调用指定的Supplier函数生成默认值。
  • orElseThrow(Supplier<? extends X> exceptionSupplier):获取Optional对象中的值,如果Optional为空,则抛出指定的异常。

通过使用Optional类,我们可以更加规范地处理可能为空的值,避免了空指针异常,并使代码更加健壮和可读性更高。

Optional的来源

  • Java 中的 Optional 类是在 Java 8 中引入的。它的目的是用于解决空指针异常(NullPointerException)的问题。在旧版本的 Java 中,如果一个方法可能返回空值,那么只能使用 null 来表示,这就导致了很多空指针异常的问题。
  • Optional 类的设计思想是将可能为空的值封装在一个对象中,并提供一系列的方法来对这个值进行操作,同时避免了空指针异常的发生。使用 Optional 类可以使代码更加健壮和可读性更高。
  • 通过使用 Optional 类,我们可以更加规范地处理可能为空的值,避免了空指针异常,并使代码更加健壮和可读性更高。

Optional方法详解

我们有一个测试对象类

class Dou{
   private Integer id;
   private String name;
}

创建Optional

  1. Optional.of(T t) : 创建一个 Optional 实例,t 必须非空(与map、flatMap配合使用)
Optional<Dou> op = Optional.of(new Dou());
  1. Optional.empty() : 创建一个空的 Optional 实例
Optional<Dou> op = Optional.empty();
  1. Optional.ofNullable(T t):t 可以为null (最常使用)
Optional<Dou> op = Optional.ofNullable(null);

判断Optional容器中是否包含对象

  1. boolean isPresent() : 判断是否包含对象
Dou dou = null;
Optional<Dou> op = Optional.ofNullable(dou);
System.out.println(op.isPresent());//false
//-----------------------------------------
dou = new Dou();
op = Optional.ofNullable(dou);
System.out.println(op.isPresent());//true
  1. void ifPresent(Consumer<? super T> consumer) :如果有值,就执行Consumer接口的实现代码,并且该值会作为参数传给它。
Dou dou = new Dou();
Optional<Dou> op = Optional.ofNullable(dou);
System.out.println(dou); //Dou(id=null, name=null)
//只有在不为null的时候执行传入的函数
op.ifPresent(d -> d.setName("an di"));
System.out.println(dou); //Dou(id=null, name=an di)

获取Optional容器的对象:

  1. T get(): 如果调用对象包含值,返回该值,否则抛异常
Dou dou = null;
Optional<Dou> op = Optional.ofNullable(dou);
System.out.println(op.get());// Exception: "No value present"
Dou dou = new Dou(1,"doudou");
Optional<Dou> op = Optional.ofNullable(dou);
System.out.println(op.get());// TestMain.Dou(id=1, name=doudou)
  1. T orElse(T other) :如果有值则将其返回,否则返回指定的other对象。
Dou dou = null;
Optional<Dou> op = Optional.ofNullable(dou);
System.out.println(op.orElse(new Dou(1,"doudou")));// TestMain.Dou(id=1, name=doudou)
  1. T orElseGet(Supplier<? extends T> other):如果有值则将其返回,否则返回由Supplier接口实现提供的对象。
Dou dou = null;
Optional<Dou> op = Optional.ofNullable(dou);
System.out.println(op.orElseGet(()-> new Dou(1,"doudou")));// TestMain.Dou(id=1, name=doudou)
Dou dou = new Dou(2,"an di");
Optional<Dou> op = Optional.ofNullable(dou);
System.out.println(op.orElseGet(()-> new Dou(1,"doudou")));// TestMain.Dou(id=2, name=an di)
  1. T orElseThrow(Supplier<? extends X> exceptionSupplier):如果有值则将其返回,否则抛出由Supplier接口实现提供的异常。
Dou dou = null;
Optional<Dou> op = Optional.ofNullable(dou);
System.out.println(op.orElseThrow(()-> new NullPointerException("为空了哦")));// Exception: 为空了哦
Dou dou = new Dou(1,"doudou");
Optional<Dou> op = Optional.ofNullable(dou);
System.out.println(op.orElseThrow(()-> new NullPointerException("为空了哦")));// TestMain.Dou(id=1, name=doudou)

过滤

  1. Optional<T> filter(Predicate<? super <T> predicate):如果值存在,并且这个值匹配给定的
    predicate,返回一个Optional用以描述这个值,否则返回一个空的Optional。
Dou dou = new Dou(1,"doudou");
Optional<Dou> op = Optional.ofNullable(dou);
op.filter( o -> o.id.equals(1)).ifPresent(System.out::println);// TestMain.Dou(id=1, name=doudou)

映射

  1. <U>Optional<U> map(Function<? super T,? extends U> mapper):如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optional。
Dou dou = new Dou(1,"doudou");
Optional<Dou> op = Optional.ofNullable(dou);
op.map( o -> o.name).ifPresent(System.out::println);//doudou
  1. <U> Optional<U> flatMap(Function<? super T, Optional<U>>mapper):如果值存在,就对该值执行提供的mapping函数调用,返回一个Optional类型的值,否则就返回一个空的Optional对象
    flatMap跟map是一样的只不过他返回的是optional对象。
Dou dou = new Dou(1,"doudou");
Optional<Dou> op = Optional.ofNullable(dou);
op.flatMap( o -> Optional.of(o.getId())).ifPresent(System.out::println);//1

实战

1. ifPresent( )函数使用

  • 原先代码
@GetMapping("/get-dateRange/{id}")
public Result getAppointDateRange(@PathVariable("id")Long id) {
    PvAppoint appoint = pvAppointService.selectPvAppointById(id);
    if (ObjUtil.isEmpty(appoint)){
        return success(ListUtil.list(false));
    }
    DateTime now = DateTime.now();//当前时间
    Date beginDate = appoint.getBeginDate();
    Date endDate = appoint.getEndDate();
    //过滤不在提前预约时间范围内
    DateTime isForwardDate = DateTime.of(beginDate).offsetNew(DateField.DAY_OF_MONTH, appoint.minusForwardDate());//提前预约时间=>考试开始时间加上提前天数
    if (now.isIn(isForwardDate, endDate)) {//在提前预约时间后 and 在考试结束时间前
        //整合时间范围
        for (DateTime time : DateUtil.rangeToList(beginDate, endDate, DateField.DAY_OF_YEAR)) {
            if (pvHolidayService.isNotHoliday(time)) {//排除节假日
                appoint.getDateRange().add(time.toDateStr());
            }
        }
    }
    return Result.success(appoint));
}
  • 使用Optional后的代码
@GetMapping("/get-dateRange/{id}")
public Result getAppointDateRange(@PathVariable("id")Long id) {
	//查询后创建Optional对象
    Optional<PvAppoint> optional = Optional.ofNullable(pvAppointService.selectPvAppointById(id));
    //如果查询数据不为空则执行ifPresent函数里的代码
    optional.ifPresent( appoint -> {
        DateTime now = DateTime.now();//当前时间
        Date beginDate = appoint.getBeginDate();
        Date endDate = appoint.getEndDate();
        //过滤不在提前预约时间范围内
        DateTime isForwardDate = DateTime.of(beginDate).offsetNew(DateField.DAY_OF_MONTH, appoint.minusForwardDate());//提前预约时间=>考试开始时间加上提前天数
        if (now.isIn(isForwardDate, endDate)) {//在提前预约时间后 and 在考试结束时间前
            //整合时间范围
            for (DateTime time : DateUtil.rangeToList(beginDate, endDate, DateField.DAY_OF_YEAR)) {
                if (pvHolidayService.isNotHoliday(time)) {//排除节假日
                    appoint.getDateRange().add(time.toDateStr());
                }
            }
        }
    });
    return Result.success(optional.orElse(new PvAppoint()));
}

未完待续…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泽泽泽json

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值