【Java】Optional的使用

为了解决空指针的一些问题,特别是方法的返回中,可能存在返回有null值的时候可以使用
java.util.Optional来处理变量;

使用Optional的好处

  1. 避免空指针异常,使用Optional的目的就是用来处理空指针异常
  2. 显示的检查Null情况,使用idea时,如果没有检查Optional直接获取值编译器会提示错误
  3. Optional提供了一些便利的方法可以更方便的处理Null的情况
  4. Optional使用了函数式编程,简化代码,避免写过多的if,可读性(不擅长函数式编程的可能有争议,但是Java8都这么久了,这方面时值得花精力扩展的)

基本使用

基于JDK8

1.定义Optional对象

1.1 定义一个空的Optional对象
Optional<String> empty = Optional.empty();
1.2 将value对象包装成Optional,此时value不能为null否则会报错
String value = "test";
Optional<String> test = Optional.of(value); 

// 当of封装的对象为null时,则会报错
Exception in thread "main" java.lang.NullPointerException
	at java.util.Objects.requireNonNull(Objects.java:203)
	at java.util.Optional.<init>(Optional.java:96)
	at java.util.Optional.of(Optional.java:108)
	at lean.sort.Solution.main(Solution.java:8)
1.3 对于可能为null的对象,包装是要使用’ofNullable’方法
String value1 = null;
Optional<String> test1 = Optional.ofNullable(value1); 

2.获取Optional对象的值

2.1判断Optional是否为空,这是一个不常用的做法。
boolean present = test.isPresent();
2.2获取Optional中的值,这是一个不常用的做法。

一般在执行get方法之前需要手动执行isPresent()方法,idea会警告;
如果此时Optional是empty的话,会报错

String str = test.get();
2.3获取Optional的值,如果为空则返回其他值

orElse() 方法会在 Optional 对象不为空时直接返回它所持有的对象,否则,它会返回传入的默认值。

orElseGet() 方法的参数是一个 Supplier 类型的函数式接口,也就是说,如果 Optional 对象不为空,该方法会直接返回所持有的对象;否则,它会调用 Supplier 函数生成一个默认值并返回。

orElseGet() 方法更加灵活,只有在Optional对象为空时才会执行方法,所有当生成默认对象的成本比较高时,使用该方法更加合适。

Optional<String> optional = getStringOptional();
// 方法一
String str = optional.orElse("other");
// 方法二
String str = optional.orElseGet(() -> "other");
2.4获取Optional的值,如果为空则抛出异常
Optional<String> optional = getStringOptional();
optional.orElseThrow(() -> new RuntimeException("value is empty"));

3.对Optional对象进行进一步链式操作

先定义初始对象

/**
 * 获取用户
 */
public class UserResource {
    public Optional<User> getUser(String name) {
        if ("name".equals(name)) {
            return Optional.of(new User("name", 18, "fullName"));
        }
        return Optional.empty();
    }
}


/**
 * 用户类
 */
public class User {
    String userName;

    int age;

    String fullName;

    public User(String userName, int age, String fullName) {
        this.userName = userName;
        this.age = age;
        this.fullName = fullName;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getFullName() {
        return fullName;
    }

    public Optional<String> getFullNameOptional() {
        return Optional.ofNullable(fullName);
    }

    public void setFullName(String fullName) {
        this.fullName = fullName;
    }
}

使用filert()方法对Optional对象进行过滤

// 该方法是获取了名称为"name"的对象,如果对象存在则判断age是否大于18
UserResource resource = new UserResource();
Optional<User> userOption = resource.getUser("name")
        .filter(user -> user.getAge() > 18);

使用map()方法和flatMap()对Optional

// 该方法是获取了名称为"name"的对象,如果对象存在则获取FullName
Optional<String> fullName1 = resource.getUser("name")
        .map(User::getFullName);
/* 
1、flatMap传入的转换函数返回的必须是一个Optional对象,flatMap会将两个Optional(执行flatMap的Option和转换函数返回的Optional)合并;
2、getFullNameOptional()方法返回的是一个Optional对象,
3、使用Map()方法返回的是一个Optional<Optional<String>>的嵌套对象
4、而使用flatMap()方法则会将Optional的嵌套合并成Optional对象
*/
Optional<String> fullName2 = resource.getUser("name")
        .flatMap(User::getFullNameOptional);
        
Optional<Optional<String>> fullName3 = resource.getUser("name")
                .map(User::getFullNameOptional);

不推荐使用Optional的场景

  1. 不要作为字段类型使用,会增加性能消耗,并且使得序列化的变得复杂;
  2. 不要作为方法参数使用,Optional的值可能为空会导致方法的执行语义不够清晰,不明确该值是否必须传递,最好通过重载的方式定义为空的情况,更具有可读性;
  3. 不要用Optional处理集合,集合已经有更好的方式去处理;
  4. 不推荐使用get()方法,使用get()方法前必须现式的进行判断(这样和显示的判断是否为null一一样了),这样无法充分利用Optional的优势。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值