《Optional》容器类使用详解

1,095 阅读5分钟

Optional

1.简介

java.util.Optional<T>

Optional主要用作方法返回类型,其中明确需要表示“无结果”,并且使用null可能导致错误。 类型为Optional变量本身不应该是null ; 它应始终指向Optional实例

注意:这是一个`value-based`类; 在`Optional`实例上使用身份敏感操作(包括引用相等( `==` ),标识哈希码或同步)可能会产生不可预测的结果,应该避免使用。

2.方法(来源于Jdk11开发文档)

image.png

3.常用方法demo演示

get()

如果存在值,则返回该值,否则抛出 NoSuchElementException
使用方式可往下看其他方法的输出方式

of()

此处不能传入对象为null的数据,如果usernull的话会报空指针异常,如果传入的是一个""空字符串的话不会报错,不过输出内容什么都没有。
User user = new User();
Optional<User> result = Optional.of(user);
System.out.println(result.get()); 

输出结果:User(name=null, sex=null, time=null)

ofNullable()

返回描述给定值的 Optional ,如果 null ,否则返回空的 Optional,此时不能进行.get()操作。
User user = new User();
Optional<User> result = Optional.ofNullable(user);
System.out.println(result.get()); 

输出结果:User(name=null, sex=null, time=null)

isPresent()

如果存在值,则返回 true ,否则返回 false
User user = new User();
Optional<User> optional = Optional.ofNullable(user);
System.out.println(optional.isPresent());

输出结果:true

isEmpty()-->JDK11出现

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

User user = new User();
user = null;
Optional<User> optional = Optional.ofNullable(user);
System.out.println(optional.isEmpty());

输出结果:true

ifPresent()

如果存在值,则使用值执行给定操作,否则不执行任何操作,如果下面给user赋值为null的话,下面则不会执行输出语句,也不会报错,输出内容什么都没有
User user = new User();
Optional<User> optional = Optional.ofNullable(user);
optional.ifPresent(e-> System.out.println("user"));

输出结果:user

ifPresentOrElse()-->JDK9出现

如果存在值,则使用值执行给定操作,否则执行给定的基于空的操作
User user = new User();
Optional<User> optional = Optional.ofNullable(user); 
optional.ifPresentOrElse( x -> System.out.println("Value: " + x),() -> System.out.println("Not Present."));
optional = Optional.empty(); // 给optional对象赋空值
optional.ifPresentOrElse( x -> System.out.println("Value: " + x),() -> System.out.println("Not Present"));

输出结果:
Value: 1
Not Present

filter()

如果存在值,并且值与给定的词匹配,则返回描述该值的 Optional ,否则返回空 Optional
User user = new User().setName("aaa");
Optional<User> optional = Optional.ofNullable(user);
optional.filter(e->"aaa".equals(e.getName())).ifPresent(e-> System.out.println("aaa"));

输出结果:aaa

User user = new User().setName("aaa");
Optional<User> optional = Optional.ofNullable(user);
optional.filter(e->"bbb".equals(e.getName())).ifPresent(e-> System.out.println("aaa"));

输出结果:
其实就是结果啥都没有,有疑问可往上看ifPresent()方法

map()

如果值存在时,返回一个Optional描述(仿佛由ofNullable(T)(ofNullable(T)) )将所述给定的映射函数的值的结果,否则返回一个空Optional 。如果映射函数返回null结果,则此方法返回空Optional
User user = new User().setName("aaa");
Optional<User> optional = Optional.ofNullable(user);
System.out.println(optional.map(User::getName).get());

输出结果:aaa

flatMap()

如果存在值,则返回将给定的Optional mapping函数应用于该值的结果,否则返回空Optional
User user = new User().setName("aaa");
Optional<User> optional = Optional.ofNullable(user);
Optional<String> user1 = optional.flatMap(e -> Optional.ofNullable(e.getName()));
System.out.println(user1.get());

输出结果:aaa

User user = new User().setName("aaa");
Optional<User> optional = Optional.ofNullable(user);
Optional<String> user1 = optional.flatMap(e -> Optional.ofNullable(e.getSex()));
System.out.println(user1);//此处没有进行.get()方法,因为sex属性没有设置值,所以调用.get()方法会报错。有疑问可往上看ofNullable()方法

输出结果:Optional.empty

orElse()

如果存在值,则返回该值,否则返回 other.
User user = new User().setName("aaa");
Optional<User> optional = Optional.ofNullable(user);
System.out.println(optional.orElse(new User().setSex("男")));

输出结果:User(name=aaa, sex=null, time=null)

User user = new User().setName("aaa");
Optional<User> optional = Optional.ofNullable(user);
optional = Optional.empty();
System.out.println(optional.orElse(new User().setSex("男")));

输出结果:User(name=null, sex=男, time=null)

orElseGet()

如果存在值,则返回该值,否则返回由供应函数生成的结果。
User user = new User().setName("aaa");
Optional<User> optional = Optional.ofNullable(user);
User user1 = optional.orElseGet(() -> new User().setName("sss"));
System.out.println(user1);

输出结果:User(name=aaa, sex=null, time=null)

User user = new User().setName("aaa");
user = null;
Optional<User> optional = Optional.ofNullable(user);
User user1 = optional.orElseGet(() -> new User().setName("sss"));
System.out.println(user1);

输出结果:User(name=sss, sex=null, time=null)

orElseThrow()

如果存在值,则返回该值,否则抛出 NoSuchElementException
User user = new User().setName("aaa");
Optional<User> optional = Optional.ofNullable(user);
User user1 = optional.orElseThrow(RuntimeException::new);
System.out.println(user1);

输出结果:User(name=aaa, sex=null, time=null)

User user = new User().setName("aaa");
user = null;
Optional<User> optional = Optional.ofNullable(user);
User user1 = optional.orElseThrow(RuntimeException::new);
System.out.println(user1);

结果:抛异常:RuntimeException
好了,大致就这些方法吧,还有一些其他的方法大家可自行前去尝试,下面有一些建议及优化案例

4.建议

1.尽量不要去使用Optional的get()方法

因为null或者是空的Optional对象调用.get()方法都会抛异常
改之前:
User user = new User().setName("aaa");
//user = null; 这里如果usernull的话,输出语句中的.get()方法就会报错~
Optional<User> optional = Optional.ofNullable(user);
System.out.println(optional.get() == null ? "name" : optional.get().getName());
改之后:
User user = new User().setName("aaa");
user = null;
Optional<User> optional = Optional.ofNullable(user);
System.out.println(optional.map(User::getName).orElse("name"));

2.尽量使用ofNullable()方法而不去用of()方法

因为当前面的对象为null的时候of方法调用会报错,使用ofNullable()方法的时候即使前面user对象为null,后面也会返回一个空的Optional对象而不是null。下面我们看代码输出结果吧!
of()方法
User user = new User().setName("aaa");
user = null;
    Optional<User> optional = Optional.of(user);// 报错位置在这一行
System.out.println(optional);

运行结果:NullPointerException 
ofNullable()方法
User user = new User().setName("aaa");
user = null;
Optional<User> optional = Optional.ofNullable(user);
System.out.println(optional.map(User::getName));

输出结果:Optional.empty
此时并没有报错,然后我们可以继续优化,加上orElse()方法预留替补方案
User user = new User().setName("aaa");
user = null;
Optional<User> optional = Optional.ofNullable(user);
System.out.println(optional.map(User::getName).orElse("sss"));

输出结果:sss

if嵌套代码优化demo

优化前
User user = new User().setName("aaa");
user.setPerson(new Person().setAge("25").setCat(new Cat().setCatName("小猫咪")));
if (Objects.nonNull(user)){
    Person person = user.getPerson();
    if (Objects.nonNull(person)){
        Cat cat = person.getCat();
        if (Objects.nonNull(cat)){
            System.out.println(cat.getCatName());
        }
    }
}
优化后
User user = new User().setName("aaa");
user.setPerson(new Person().setAge("25").setCat(new Cat().setCatName("小猫咪")));
String catName = Optional.ofNullable(user)
        .flatMap(user1 -> Optional.ofNullable(user1.getPerson()))
        .flatMap(person -> Optional.ofNullable(person.getCat()))
        .flatMap(cat -> Optional.ofNullable(cat.getCatName()))
        .orElse("");
System.out.println(catName);

1664524829516.jpg

欢迎各路大佬来指正我的不足之处~