【Java8新特性】——Optional

前提

    著名的NullPointerException是导致Java应用程序失败的最常见原因,而在Java8中对这种常见错误提出了Optional类(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 empty = Optional.empty();

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

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

2、流式处理

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

map——map(Function mapper)

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

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

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

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

flatMap——flatMap(Function> mapper)

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

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

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

3、默认行为

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

        Optional 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 toUpperCase = Optional.ofNullable(str.toString().toUpperCase());

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

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

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

        //7、filter(Predicate predicate)
        //如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional
        Optional 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, 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 getPhone() {
    return Optional.ofNullable(this.phone);
}

4、其他

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

总结

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

你可能感兴趣的:(【Java】,——【Java新特性】,Java8,9新特性)