文章目录

  • 前言
  • Optional 类
  • 1.概述
  • 2.API介绍
  • of
  • ofNullable
  • empty
  • isPresent
  • get
  • ifPresent
  • orElse
  • orElseGet
  • orElseThrow
  • map
  • flatMap
  • filter
  • 3.Optional应用



前言

Optional就是一个很重要的特性,它主要功能是解决NPE(NullPointerException)问题!

Optional 类

1.概述

 Optional不是函数式接口,而是用于防止 NullPointerException 的漂亮工具。这是下一节的一个重要概念,让我们快速了解一下Optional的工作原理。

 Optional 是一个简单的容器,其值可能是null或者不是null。在Java 8之前一般某个函数应该返回非空对象但是有时却什么也没有返回,而在Java 8中,你应该返回 Optional 而不是 null。

2.API介绍

of

为非null的值创建一个Optional。

of()方法通过工厂方法创建Optional类。需要注意的是,创建对象时传入的参数不能为null。如果传入参数为null,则抛出NullPointerException 。

代码如下(示例):

//调用工厂方法创建Optional实例
Optional<String> stringOpt = Optional.of("林深时见鹿");
//传入参数为null,则抛出 java.lang.NullPointerException
Optional<String> stringOpt1 = Optional.of(null);

ofNullable

为指定的值创建一个Optional,如果指定的值为null,则返回一个空的Optional。

ofNullable()与of方法相似,唯一的区别是可以接受参数为null的情况。

代码如下(示例):

//创建允许为空的Optional对象
Optional opt = Optional.ofNullable(null); //不会报错

empty

一个空的Optional。

代码如下(示例):

//一个空的Optional
Optional<String> empty = Optional.empty();

isPresent

如果值存在返回true,否则返回false。

代码如下(示例):

Optional<String> stringOpt = Optional.of("林深时见鹿");
//isPresent方法如果值存在返回true,否则返回false。
if (stringOpt.isPresent()) {
    //在Optional实例内调用get()返回已存在的值    
    System.out.println(stringOpt.get()); //林深时见鹿
}

get

代码如下(示例):

//一个空的Optional
Optional<String> empty = Optional.empty();
//执行下面的代码会输出:No value present
try {
    //在空的Optional实例上调用get(),抛出NoSuchElementException
    System.out.println(empty.get());
} catch (NoSuchElementException ex) {
    System.out.println(ex.getMessage());
}

ifPresent

如果Optional实例有值则为其调用consumer,否则不做处理

代码如下(示例):

//ifPresent方法接受lambda表达式作为参数,lambda表达式对Optional的值调用consumer进行处理
Optional.ofNullable(null).ifPresent(u ->  System.out.println("是 null 的,不做处理"));
Optional.ofNullable("林深时见鹿").ifPresent(u ->  System.out.println("不是 null 的,做处理"));

//输出:不是 null 的,做处理

注意: 通过ifPresent()修改的值,再次通过get()获取的时候不会改变。

orElse

如果有值则将其返回,否则返回指定的其它值。

如果Optional实例有值则将其返回,否则返回orElse()方法传入的参数。

代码如下(示例):

//如果值不为null,orElse方法返回 Optional实例的值
//如果为null,返回传入的指定指
Optional opt1 = Optional.ofNullable(null);
Optional opt2 = Optional.ofNullable("林深时见鹿");
System.out.println(opt1.orElse("指定的值")); //指定的值
System.out.println(opt2.orElse("指定的值")); //林深时见鹿

orElseGet

orElseGet()与orElse方法类似,区别在于得到的默认值。orElse方法将传入的字符串作为默认值,orElseGet方法可以接受Supplier接口的实现用来生成默认值。

代码如下(示例):

//orElseGet与orElse方法类似,区别在于orElseGet可以接受一个lambda表达式生成默认值
Optional opt1 = Optional.ofNullable(null);
Optional opt2 = Optional.ofNullable("林深时见鹿");
System.out.println(opt1.orElseGet( () -> "指定的值")); //指定的值
System.out.println(opt2.orElseGet( () ->"指定的值"));  //林深时见鹿

orElseThrow

如果有值则将其返回,否则抛出supplier接口创建的异常。

在orElseGet方法中,我们传入一个Supplier接口。然而,在orElseThrow()中我们可以传入一个lambda表达式或方法,如果值不存在来抛出异常。

代码如下(示例):

//orElseThrow会抛出lambda表达式或方法生成的异常
//一个空的Optional
Optional<String> empty = Optional.empty();
try {
    empty.orElseThrow( () -> new Exception() );
} catch (Throwable ex) {
    ex.printStackTrace();
}

map

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

代码如下(示例):

//map执行传入的lambda表达式参数对Optional实例的值进行修改,lambda表达式的返回值创建新的Optional实例作为map方法的返回值
Optional<String> stringOpt = Optional.of("aBcDefg");
Optional<String> upperName = stringOpt.map((value) -> value.toUpperCase());
System.out.println(upperName.orElse("No value found"));

//输出:ABCDEFG

flatMap

如果有值,为其执行mapping函数返回Optional类型返回值,否则返回空Optional。flatMap()与map(Funtion)方法类似,区别在于flatMap中的mapper返回值必须是Optional。调用结束时,flatMap不会对结果用Optional封装。

代码如下(示例):

//flatMap与map(Function)非常类似,区别在于传入方法的lambda表达式的返回类型
//flatMap方法中的lambda表达式返回值必须是Optional实例
Optional<String> stringOpt = Optional.of("aBcDefg");
Optional<String> upperName = stringOpt.flatMap((value) -> Optional.of(value.toUpperCase()));
System.out.println(upperName.orElse("No value found"));

//输出:ABCDEFG

filter

如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional。

代码如下(示例):

//filter方法检查给定的Option值是否满足某些条件,如果满足则返回同一个Option实例,否则返回空Optional
Optional<Integer> intOpt = Optional.of(5);
Optional<Integer> longName = intOpt.filter((value) -> value > 6);
System.out.println(longName.orElse(0)); //0

3.Optional应用

  • Optional.of(obj):它要求传入的 obj 不能是 null 值的,否则还没开始进入角色就倒在了 NullPointerException 异常上了
  • Optional.ofNullable(obj):它以一种智能的,宽容的方式来构造一个 Optional 实例,来者不拒,传 null 进到就得到 Optional.empty(),非 null 就调用 Optional.of(obj)

代码如下(示例):

Optional<User> user = Optional.of(user1);
//orElse() map()是可能无限级联的,获得用户名的大写形式,否则返回默认值空
return user.map(u -> u.getUsername())
           .map(name -> name.toUpperCase())
           .orElse(null);

//orElseGet() 与orElse()类似,只不过没有值就用函数式接口
User result = Optional.ofNullable(user1).orElseGet( () -> user2);

//orElseThrow() 如果user值为null,会抛出 IllegalArgumentException
User result = Optional.ofNullable(user)
      .orElseThrow( () -> new IllegalArgumentException());

//filter() 根据基本的电子邮箱验证来决定接受或拒绝 User
Optional<User> result = Optional.ofNullable(user)
      .filter(u -> u.getEmail() != null && u.getEmail().contains("@"));

当想为 obj 断言不为 null 时,即我们想在万一 obj 为 null 立即报告 NullPointException 异常, 立即修改,而不是隐藏空指针异常时,我们就应该果断的用 Optional.of(obj) 来构造 Optional 实例, 而不让任何不可预计的 null 值有可乘之机隐身于 Optional 中。

@Data
public class Student {
    private String name = "林深时见鹿";
    private String sex = "男";
}

// 1、创建一个包装对象值为空的Optional对象
Optional<Student> studentOpt = Optional.empty();
// 2、创建包装对象值非空的Optional对象
Optional<Student> studentOpt1 = Optional.of(new Student());
// 3、创建包装对象值允许为空的Optional对象
Optional<Student> studentOpt2 = Optional.ofNullable(null);

System.out.println(studentOpt.get().getName()); // 打印:NoSuchElementException
System.out.println(studentOpt.orElse(new Student()).getName()); // 打印:林深时见鹿

System.out.println(studentOpt1.get().getName()); // 打印:林深时见鹿

System.out.println(studentOpt2.get().getName()); // 打印:NoSuchElementException
System.out.println(studentOpt2.orElse(new Student()).getName()); // 打印:林深时见鹿

System.out.println(studentOpt.isPresent()); // 打印:false
System.out.println(studentOpt1.isPresent()); // 打印:true

Optional 可以创建任意类型的对象,并且通过 get() 方法获取特定的对象,创建 Optional 为空时,获得的对象就是空的,但是可以通过 orElse 来判断,如果为空,再通过orElse 的参数重新创建。isPresent() 方法用于判断 Optional 封装的对象是否为空。

Student studentNull = null;
Student student = new Student();
Optional.ofNullable(studentNull).ifPresent(u ->  System.out.println("这个对象是null的"));
Optional.ofNullable(student).ifPresent(u ->  System.out.println("这个对象是不是null的"));

//输出:这个对象是不是NULL的

ifPresent() 方法接受一个Consumer对象(消费函数),如果包装对象的值非空,运行Consumer对象的accept()方法。这样的话就可以愉快的用 Lambda 表达式了。

Optional.ofNullable(studentNull)
        .filter(u -> "林深时见鹿".equals(u.getName()))
        .ifPresent(u ->  System.out.println("studentNull,名字与“林深时见鹿”目标相等"));
Optional.ofNullable(student)
        .filter(u -> "林深时见鹿".equals(u.getName()))
        .ifPresent(u ->  System.out.println("student,名字与“林深时见鹿”目标相等"));
Optional.ofNullable(student)
        .filter(u -> "张三".equals(u.getName()))
        .ifPresent(u ->  System.out.println("student,名字与“张三”目标相等"));

//输出:student,名字与“林深时见鹿”目标相等

filter()方法也是非常实用的,这个方法用于对 Optional 对象进行过滤,如果符合条件的,返回Optional对象本身,否则返回一个空的Optional对象。

System.out.println(Optional.ofNullable(student).map(u -> u.getName()).get());
System.out.println(Optional.ofNullable(studentNull).map(u -> u.getName())); //u.getName()).get() 会报错
//输出:
//林深时见鹿
//Optional.empty
    
System.out.println(Optional.ofNullable(student).map(u -> u.getName()).orElse("这个可能是空"));
System.out.println(Optional.ofNullable(studentNull).map(u -> u.getName()).orElse("这个一定是空"));
//输出:
//林深时见鹿
//这个一定是空

先用ofNullable()方法构造一个Optional对象,返回Optional对象(如果 student 为 null, 返回 map() 方法返回一个空的 Optinal 对象)。如果 u.getName()).get() 获取不到会发生异常,所以用 orElse 来代替。

再用 orElse 方法替代 get 方法,orElse()方法功能比较简单,即如果包装对象值非空,返回包装对象值,否则返回入参other的值(默认值)。


java 中的Global类 java optional类_默认值