【Java8新特性】——Optional

前提

    著名的NullPointerException是导致Java应用程序失败的最常见原因,而在Java8中对这种常见错误提出了Optional<T>类(java.util.Optional)是一个容器类,代表一个值存在或不存在。Optional不是对null关键字的一种替代,而是对于null判定提供了一种更加优雅的实现,还可以避免空指针异常。
    空指针是运行时异常,对于这一类异常,大多数情况下,不是没有具体的处理措施,而是根本没有意识到空指针异常的存在。当异常发生的时候,处理策略非常简单,加一个if语句判定即可。良好的程序设计,在代码中尽可能减少null关键字!而Java8中提供的Optional类则在减少NullPointException的同时,提升代码的美观度。

没有Optional

if(null == str) { // 空指针判定
    return 0;
}
return str.length();

使用Optional类,如下

return Optional.ofNullable(str).map(String::length).orElse(0);

Optional基本使用方式

1、对象创建

        //1、创建一个空Optional对象
        Optional<Object> empty = Optional.empty();

        //2、创建对象,如果str对象为null,则会抛出NullPointException
        String str = "test";
        Optional<String> optStr = Optional.of(str);

        //3、创建对象,如果str对象非null,则返回一个Optional描述指定的值,否则返回空值Optional
        Optional<String> optStrNotNull = Optional.ofNullable(str);

2、流式处理

Optional提供两个基本流操作,映射和过滤。

map——map(Function<? super T,? extends U> mapper)

如果存在值,则将提供的映射函数应用于该函数,如果结果不为空,则返回Optional描述结果。

注意:如果有值,则对其执行调用mapping函数得到返回值。如果返回值不为null,则创建包含mapping返回值的Optional作为map方法返回值,否则返回空Optional。

map方法中的lambda表达式返回值可以是任意类型,在map函数返回之前会包装为Optional。

        //map方法中的lambda表达式返回值可以是任意类型,在map函数返回之前会包装为Optional。
        Optional<Object> map = op.map( Employess::getAge ).map( t -> Optional.get( t ) );
        Integer mapAge = op.map( Employess::getAge ).orElse( 19 );

flatMap——flatMap(Function<? super T,Optional<U>> mapper)

如果存在值,则将提供的Optional映射函数应用于该函数,返回该结果,否则返回空值 Optional。

注意:flatMap方法中的lambda表达式返回值必须是Optionl实例。

//       flatMap方法中的lambda表达式返回值必须是Optionl实例。
        Integer flatAge = op.flatMap( emp -> Optional.of( emp.getAge() ) ).orElse( 19 );

3、默认行为

默认行为是当Optional为不满足/满足时条件时所执行的操作。

        Optional<String> str = Optional.of("test");
        //1、判断str是否为null,如果不为null,则为true,否则为false
        if (str.isPresent()) {
            //get用于获取变量的值,当变量不存在的时候会抛出NoSuchElementException,如果不能确定变量一定存在值,则不推荐使用
            str.get();
        }

        //2、如果存在值,则使用该值调用消费者,否则不执行任何操作
        str.ifPresent(s -> System.out.println(s.toUpperCase()));

        // 3、ofNullable(T value)(静态)返回一个Optional描述指定的值,如果非null,否则返回一个空值Optional。
        Optional<String> toUpperCase = Optional.ofNullable(str.toString().toUpperCase());

        //4、orElse(T other) 返回值如果存在,则返回,否则返回 other
        String s = str.orElse("str is null");

        //5、orElseGet(Supplier<? extends T> other)返回值如果存在,否则调用other并返回该调用的结果
        String orElseGet = str.orElseGet(() -> "test".toUpperCase());
        System.out.println(orElseGet);

        //6、orElseThrow(Supplier<? extends X> exceptionSupplier)
        // 返回包含的值(如果存在),否则抛出由提供的供应商创建的异常。
        str.orElseThrow(NoSuchElementException::new);

        //7、filter(Predicate<? super T> predicate)
        //如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional
        Optional<String> filterOpt = str.filter(value -> value.length() > 3);
注意:
       if(null == str) { // 空指针判定
             return 0;
             }
         return str.length();

利用Optional if中的判断和处理,本质上和if null没有区别,当然这不是更好使用Java8 Optional正确的打开方式。

在IDEA中没有isPresent()做铺垫的get()会收到警告

Reports calls to java.util.Optional.get() without first checking with a isPresent() call if a value is available. If the Optional does not contain a value, get() will throw an exception. (调用 Optional.get() 前不事先用 isPresent() 检查值是否可用. 假如 Optional 不包含一个值, get() 将会抛出一个异常)

把 Optional 类型用作属性或是方法参数在 IntelliJ IDEA 中更是强力不推荐的

Reports any uses of java.util.Optional<T>, java.util.OptionalDouble, java.util.OptionalInt, java.util.OptionalLong or com.google.common.base.Optional as the type for a field or a parameter. Optional was designed to provide a limited mechanism for library method return types where there needed to be a clear way to represent “no result”. Using a field with type java.util.Optional is also problematic if the class needs to be Serializable, which java.util.Optional is not. (使用任何像 Optional 的类型作为字段或方法参数都是不可取的. Optional 只设计为类库方法的, 可明确表示可能无值情况下的返回类型. Optional 类型不可被序列化, 用作字段类型会出问题的)

如果一定要使用Optional作为属性,可以使用如下方式

private long phone;

public Optional<Long> getPhone() {
    return Optional.ofNullable(this.phone);
}

4、其他

//        返回当前值的哈希码值(如果有的话),如果没有值,则返回0(零)。
        int hashCode = str.hashCode();
//        返回适用于调试的此可选的非空字符串表示形式。
        String s1 = str.toString();

总结

   多去尝试新的特性,尽力提高自己的代码质量,是程序员的基本的职业素养!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 18
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Mandy_i

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

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

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

打赏作者

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

抵扣说明:

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

余额充值