jdk1.8新增特性Optional类介绍


jdk1.8新增了一个Optional类,同时还增加了OptionalDouble、OptionalInt,OptionalLong用于对基本类型double、int、long的支持。

Optional的使用场景介绍

有时候我们需要从一个对象中获取其成员变量,甚至需要获取其成员变量的变量,通常为了避免产生空指针异常需要进行非空校验,当嵌套层次较多时存在多层嵌套的if非空判断,看如下代码,UserInfo表示用户,为了获取用户的曾祖父信息,我们使用了差不多用户了12行的代码,其中除了打印曾祖父信息之外其它的都是嵌套非空判断,代码显得很冗余笨拙:

public class OptionalTest {
    static class UserInfo {
        private int id;
        private String name;
        private UserInfo father;

        public UserInfo(int id, String name, UserInfo father) {
            this.id = id;
            this.name = name;
            this.father = father;
        }

        @Override
        public String toString() {
            return "UserInfo{" + "id=" + id + ", name='" + name + '\'' + '}';
        }
    }
    public static void main(String[] args) {
        UserInfo ui = new UserInfo(1, "张三", null);
        UserInfo greatGrandFather = null;
        if (ui != null) {
            UserInfo father = ui.father;
            if (father != null) {
                UserInfo grandFather = father.father;
                if (grandFather != null) {
                    greatGrandFather = grandFather.father;
                }
            }
        }
        if (greatGrandFather != null) {
            System.out.println(greatGrandFather );
        }
    }
}

反之使用Optional来实现同样的判断将使得代码精简且优雅很多,只需一行代码即可,具体如下:

    public static void main(String[] args) {
        UserInfo ui = new UserInfo(1, "张三", null);
        Optional.ofNullable(ui).map(u->u.father).map(u->u.father).map(u->u.father).ifPresent(System.out::println);
    }

Optional的方法介绍

从上可知Optional主要用于对象可能为null的情况下,需要对对象进行相关操作时简化非空校验的一个容器,同时其相关操作后都会返回一个Optional对象可用于来连续方法调用。其构造器私有化不允许用户直接通过构造器获取Optional实例,因此Optional提供了两个静态方法用于获取对象的Optional实例。两个静态方法介绍如下:

  • public static Optional of(T value):传入的value不允许为null,否则将抛出NullPointerException异常
  • public static Optional ofNullable(T value):相比of该方法允许传入的value为null

获取到对象的封装对象后,我们就可以使用其提供的便捷方法了,介绍如下:

  • public T get():获取原值,如果原值为null,将抛出NoSuchElementException异常
  • public boolean isPresent():判断原值是否为null,为null返回false
  • ofElse(T t):当原值为null时返回t,否则返回原值

上述几个方法是Optional提供的最基本的用法,下面对几个比较实用的方法进行示例

  • public T orElseGet(Supplier<? extends T> other):当原值!=null时返回原值,否则返回other提供的值
    public static void main(String[] args) {
        UserInfo ui = new UserInfo(1, "张三", null);
        //当ui == null式输出张三copy信息,否则输出张三信息
        System.out.println(Optional.ofNullable(ui).orElseGet(()-> new UserInfo(11,"张三copy",null)));
}
  • public T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X:当原值!=null时返回原值,否则抛出由exceptionSupplier提供的异常对象
    public static void main(String[] args) {
        UserInfo ui = null;//new UserInfo(1, "张三", null);
        //当ui==null时,将抛出IllegalStateException("值为null")异常,否则正常返回原值
        System.out.println(Optional.ofNullable(ui).orElseThrow(()->new IllegalStateException("值为null")));
    }
  • public Optional filter(Predicate<? super T> predicate):原值过滤并返回一个原值可为null的Optional
    public static void main(String[] args) {
        UserInfo ui = new UserInfo(1, "张三", null);
        //当ui的id>1时返回ui,否则返回null
        System.out.println(Optional.ofNullable(ui).filter(u->u.id > 0).orElse(null));
    }
  • public Optional flatMap(Function<? super T, Optional> mapper):返回值由mapper自定义,要求mapper必须返回一个Optional对象。
    public static void main(String[] args) {
        UserInfo ui = new UserInfo(1, "张三", null);
        //当ui.id==1时,将ui.name更改并返回一个可为空或不可谓空的Optional
        System.out.println(Optional.of(ui).flatMap(u->{
            if(u.id == 1)
                u.name = "张三更改名字";
            return Optional.of(u);//或则Optional.ofNullable(u),可自定义返回的Optional是否允许null值
        }).orElse(null));
    }
  • public Optional map(Function<? super T, ? extends U> mapper):和flatMap功能相似,相对于flatMap,map默认返回一个ofNullable的Optional对象。
    public static void main(String[] args) {
        UserInfo ui = new UserInfo(1, "张三", null);
        //当ui.id==1时,将ui.name更改并返回一个可为空的Optional
        System.out.println(Optional.of(ui).map(u->{
            if(u.id == 1)
                u.name = "张三更改名字";
            return u;//或则Optional.ofNullable(u),可自定义返回的Optional是否允许null值
        }).orElse(null));
    }

OptionalDouble、OptionalInt,OptionalLong介绍

当我们使用基本类型(int,double,long)作为方法入参时,有时候对于基本类型的值感到不解,比如对于对于如下方法:当annualProfit=0时到底表示收支相等还是一年根本没有任何收支信息?如果需要区分这这种情况如何区分?当然了你可以使用封装类型为null进行判断,但封装类型在使用时需要拆盒或装盒功能,如果计算量非常大时对性能还是有所影响的,这个时候可以使用OptionalDouble类来实现。

    public void showAnnualProfit(double annualProfit){
        System.out.println("个人年结余金额为:"+annualProfit);
    }

OptionalDouble实现

    public void showAnnualProfit(OptionalDouble annualProfit){
        if(annualProfit.isPresent()){
            System.out.println("个人年结余金额为:"+annualProfit.getAsDouble());
        }else{
            System.out.println("无个人收支信息");
        }
    }

OptionalInt,OptionalLong和OptionalDouble相差不大,从源码中可以看出他们没有Optional提供的一系列函数式入参对应的方法,基本类型不支持相应的泛型申明,同时也没必要对基本类型应用复杂的函数式功能。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值