文章目录
- 前言
- 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的值(默认值)。