欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用Java8中的Optional类来消除代码中的null检查

程序员文章站 2022-03-04 11:04:32
...

java.util.Optional<T>

是一个封装了Optional值的容器对象,Optional值可以为null,如果值存在,调用isPresent()方法返回true,调用get()方法可以获取值。

//empty()方法用于创建一个没有值的Optional对象:

   Optional<String> emptyOpt = Optional.empty();

//empty()方法创建的对象没有值,如果对emptyOpt变量调用isPresent()方法会返回false,调用get()方法抛//出NullPointerException异常。



//of()方法使用一个非空的值创建Optional对象:

String str = "Hello World";
Optional<String> notNullOpt = Optional.of(str);


//ofNullable()方法接收一个可以为null的值:
Optional<String> nullableOpt = Optional.ofNullable(str);

//如果str的值为null,得到的nullableOpt是一个没有值的Optional对象。

 

提取Optional对象中的值 

Optional<User> userOpt = Optional.ofNullable(user);
Optional<String> roleIdOpt = userOpt.map(User::getRoleId);

使用orElse()方法获取值

  • orElse():如果有值就返回,否则返回一个给定的值作为默认值;

  • orElseGet():与orElse()方法作用类似,区别在于生成默认值的方式不同。该方法接受一个Supplier<? extends T>函数式接口参数,用于生成默认值;

  • orElseThrow():与前面介绍的get()方法类似,当值为null时调用这两个方法都会抛出NullPointerException异常,区别在于该方法可以指定抛出的异常类型。

三个方法的具体用法:

String str = "Hello World";
Optional<String> strOpt = Optional.of(str);
String orElseResult = strOpt.orElse("Hello Shanghai");
String orElseGet = strOpt.orElseGet(() -> "Hello Shanghai");
String orElseThrow = strOpt.orElseThrow(
        () -> new IllegalArgumentException("Argument 'str' cannot be null or blank."));

此外,Optional类还提供了一个ifPresent()方法,该方法接收一个Consumer<? super T>函数式接口,一般用于将信息打印到控制台:

Optional<String> strOpt = Optional.of("Hello World");
strOpt.ifPresent(System.out::println);

使用filter()方法过滤

filter()方法可用于判断Optional对象是否满足给定条件,一般用于条件过滤:

Optional<String> optional = Optional.of("[email protected]");
optional = optional.filter(str -> str.contains("164"));

在上面的代码中,如果filter()方法中的Lambda表达式成立,filter()方法会返回当前Optional对象值,否则,返回一个值为空的Optional对象。

Java 8提倡函数式编程,新增的许多API都可以用函数式编程表示,Optional类也是其中之一。这里有几条关于Optional使用的建议:

  • 尽量避免在程序中直接调用Optional对象的get()和isPresent()方法;

  • 避免使用Optional类型声明实体类的属性;

第一条建议中直接调用get()方法是很危险的做法,如果Optional的值为空,那么毫无疑问会抛出NullPointerException异常,而为了调用get()方法而使用isPresent()方法作为空值检查,这种做法与传统的用if语句块做空值检查没有任何区别。

第二条建议避免使用Optional作为实体类的属性,它在设计的时候就没有考虑过用来作为类的属性,如果你查看Optional的源代码,你会发现它没有实现java.io.Serializable接口,这在某些情况下是很重要的(比如你的项目中使用了某些序列化框架),使用了Optional作为实体类的属性,意味着他们不能被序列化。

 

正确创建Optional对象

上面提到创建Optional对象有三个方法,empty()方法比较简单,没什么特别要说明的。主要是of()和ofNullable()方法。当你很确定一个对象不可能为null的时候,应该使用of()方法,否则,尽可能使用ofNullable()方法,比如:

public static void method(Role role) {
    // 当Optional的值通过常量获得或者通过关键字new初始化,可以直接使用of()方法
    Optional<String> strOpt = Optional.of("Hello World");
    Optional<User> userOpt = Optional.of(new User());

    // 方法参数中role值不确定是否为null,使用ofNullable()方法创建
    Optional<Role> roleOpt = Optional.ofNullable(role);
}

orElse()方法的使用(里面不可以放方法,不管是否为空,都会调用)

return str != null ? str : "Hello World"

return strOpt.orElse("Hello World")
User user = ...
if (user != null) {
    String userName = user.getUserName();
    if (userName != null) {
        return userName.toUpperCase();
    } else {
        return null;
    }
} else {
    return null;
}




//上面的代码可以简化成:
User user = ...
Optional<User> userOpt = Optional.ofNullable(user);

return userOpt.map(User::getUserName)
            .map(String::toUpperCase)
            .orElse(null);




User result = Optional.ofNullable(user).orElse(user2);



User result2 = Optional.ofNullable(user).orElseGet(() -> createNewUser());
String email = Optional.ofNullable(user).map(u -> u.getEmail()).orElse("default");

//解除包装
String position = Optional.ofNullable(user).flatMap(u -> u.getPosition()).orElse("default");

//过滤
Optional<User> result = Optional.ofNullable(user).filter(u -> u.getEmail() != null && u.getEmail().contains("@"));

//链式调用
String result = Optional.ofNullable(user)
  .flatMap(User::getAddress)
  .flatMap(Address::getCountry)
  .map(Country::getIsocode)
  .orElse("default");


//orElseGet方法调用,最终目的是获取返回值
 public static void main(String[] args) {
        String a = null;
        String s2 = Optional.ofNullable(a).orElseGet(() -> {
            String test = test();
            return test;
        });
        System.out.println(s2);


    }
    private static String  test(){
        return "2";
    }
     

ifPresent用法(不为null时候,执行某个方法)

opt.ifPresent( u -> assertEquals(user.getEmail(), u.getEmail()));

去包装获取数据

HashMap<String, Object> opMap = new HashMap<>();
        opMap.put("timeLoopType","w");
        boolean timeLoopType = Optional.ofNullable(opMap).map(strMap -> strMap.get("timeLoopType")).isPresent();
        Optional<Object> timeLoopType1 = Optional.ofNullable(opMap).map(strMap -> strMap.get("timeLoopType"));
        System.out.println(timeLoopType);
        System.out.println(timeLoopType1.orElseGet(()->{return "111";} ));
        System.out.println(timeLoopType1.orElseGet(()->  "111"   ));

 

 

相关标签: optional java