重学JDK8新特性之Optional

简介: 重学JDK8新特性之Optional

以前对NULL的处理


//String userName = "张三";
String userName = null;
if(userName != null){
  System.out.println("字符串的长度:" + userName.length());
}else{
  System.out.println("字符串为空");
}


Optional类


Optional是一个没有子类的工具类,Optional是一个可以为null的容器对象,它的主要作用就是为了避

免Null检查,防止NullpointerException


Optional的基本使用


// 第一种方式 通过of方法 of方法是不支持null的
Optional<String> op1 = Optional.of("zhangsan");
//Optional<Object> op2 = Optional.of(null);
// 第二种方式通过 ofNullable方法 支持null
Optional<String> op3 = Optional.ofNullable("lisi");
Optional<Object> op4 = Optional.ofNullable(null);
// 第三种方式 通过empty方法直接创建一个空的Optional对象
Optional<Object> op5 = Optional.empty();


Optional的常用方法


/**
* Optional中的常用方法介绍
* get(): 如果Optional有值则返回,否则抛出NoSuchElementException异常
* get()通常和isPresent方法一块使用
* isPresent():判断是否包含值,包含值返回true,不包含值返回false
* orElse(T t):如果调用对象包含值,就返回该值,否则返回t
* orElseGet(Supplier s):如果调用对象包含值,就返回该值,否则返回 Lambda表达式的返
回值
*/
Optional<String> op1 = Optional.of("zhangsan");
Optional<String> op2 = Optional.empty();
// 获取Optional中的值
if(op1.isPresent()){
  String s1 = op1.get();
  System.out.println("用户名称:" +s1);
}
if(op2.isPresent()){
  System.out.println(op2.get());
}else{
  System.out.println("op2是一个空Optional对象");
}
String s3 = op1.orElse("李四");
System.out.println(s3);
String s4 = op2.orElse("王五");
System.out.println(s4);
String s5 = op2.orElseGet(()->{
  return "Hello";
});
System.out.println(s5);
Person p = new Person("zhangsan",18);
Optional<Person> op = Optional.of(p);
String name = getNameForOptional(op);
System.out.println("name="+name);
public String getNameForOptional(Optional<Person> op){
  if(op.isPresent()){
    String msg = //op.map(p -> p.getName())
      op.map(Person::getName)
      //.map(p -> p.toUpperCase())
      .map(String::toUpperCase)
      .orElse("空值");
    return msg;
  }
return null;
}


额外补充三个常用的:


获取Optional容器的对象:


  • T orElseThrow(Supplier<? extends X> exceptionSupplier) :如果有值则将其返回,否则抛出由Supplier接口实现提供的异常。


过滤:


  • Optional<T> filter(Predicate<? super <T> predicate):如果值存在,并且这个值匹配给定的 predicate,返回一个Optional用以描述这个值,否则返回一个空的Optional。


映射


  • <U>Optional<U> map(Function<? super T,? extends U> mapper):如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optional。


Optional实战


这部分是通过查阅实际上开发中写法总结出来的,并不是只介绍了Optional的概念,而是融入了实际开发中考虑到的情况,实际上在开发中空指针异常的异常很常见,而灵活的的使用Optional能够很好的避免这种情况。


场景一:


PatientInfo patientInfo = patientInfoDao.getPatientInfoById(consultOrder.getPatientId());
if (patientInfo != null) {
    consultInfoResp.setPatientHead(patientInfo.getHead());
}
// 使用Optional 和函数式编程,一行搞定,而且像说话一样
Optional.ofNullable(patientInfo).ifPresent(p -> consultInfoResp.setPatientHead(p.getHead()));


场景二:


public void test1() throws Exception {
    Student student = new Student(null, 3);
    if (student == null || isEmpty(student.getName())) {
        throw new Exception();
    }
    String name = student.getName();
    // 业务省略...
    // 使用Optional改造
    Optional.ofNullable(student).filter(s -> !isEmpty(s.getName())).orElseThrow(() -> new Exception());
}
public static boolean isEmpty(CharSequence str) {
    return str == null || str.length() == 0;
}


场景三:


public static String getChampionName(Competition comp) throws IllegalArgumentException {
    if (comp != null) {
        CompResult result = comp.getResult();
        if (result != null) {
            User champion = result.getChampion();
            if (champion != null) {
                return champion.getName();
            }
        }
    }
    throw new IllegalArgumentException("The value of param comp isn't available.");
}

这个在开发中是很常见的一种逻辑。去判读传进来的参数时候为空,或者是从数据库中获取的对象。由于某些原因,我们不能很流程的直接这样写。

comp.getResult().getChampion().getName()

上面的写法用Optional改写:

public static String getChampionName(Competition comp) throws IllegalArgumentException {
    return Optional.ofNullable(comp)
            .map(Competition::getResult)  // 相当于c -> c.getResult(),下同
            .map(CompResult::getChampion)
            .map(User::getName)
            .orElseThrow(()->new IllegalArgumentException("The value of param comp isn't available."));
}


场景四:


int timeout = Optional.ofNullable(redisProperties.getTimeout())
            .map(x -> Long.valueOf(x.toMillis()).intValue())
            .orElse(10000);


目录
相关文章
|
21天前
|
容器
jdk8新特性-详情查看文档
jdk8新特性-详情查看文档
39 7
|
3月前
|
容器
jdk8新特性-详情查看文档
jdk8新特性-详情查看文档
48 3
|
2月前
|
存储 安全 Java
JDK1.8 新的特性
JDK1.8 新的特性
29 0
|
3月前
|
编解码 安全 Java
jdk8新特性-接口和日期处理
jdk8新特性-接口和日期处理
|
4月前
|
Java API
JDK8到JDK25版本升级的新特性问题之使用Collectors.teeing()来计算一个列表中学生的平均分和总分如何操作
JDK8到JDK25版本升级的新特性问题之使用Collectors.teeing()来计算一个列表中学生的平均分和总分如何操作
|
4月前
|
Java API Apache
JDK8到JDK24版本升级的新特性问题之在Java中,HttpURLConnection有什么局限性,如何解决
JDK8到JDK24版本升级的新特性问题之在Java中,HttpURLConnection有什么局限性,如何解决
|
4月前
|
Oracle Java 关系型数据库
JDK8到JDK29版本升级的新特性问题之未来JDK的升级是否会成为必然趋势,如何理解
JDK8到JDK29版本升级的新特性问题之未来JDK的升级是否会成为必然趋势,如何理解
|
4月前
|
Oracle 安全 Java
JDK8到JDK28版本升级的新特性问题之在Java 15及以后的版本中,密封类和密封接口是怎么工作的
JDK8到JDK28版本升级的新特性问题之在Java 15及以后的版本中,密封类和密封接口是怎么工作的
|
4月前
|
Java API 开发者
JDK8到JDK17版本升级的新特性问题之SpringBoot选择JDK17作为最小支持的Java lts版本意味着什么
JDK8到JDK17版本升级的新特性问题之SpringBoot选择JDK17作为最小支持的Java lts版本意味着什么
154 0
JDK8到JDK17版本升级的新特性问题之SpringBoot选择JDK17作为最小支持的Java lts版本意味着什么
|
3月前
|
Java 编译器 API
JDK8新特性--lambda表达式
JDK8的Lambda表达式是Java语言的一大进步。它为Java程序提供了更多的编程方式,让代码更加简洁,也让函数式编程的概念在Java中得到了体现。Lambda表达式与Java 8的其他新特性,如Stream API、新的日期时间API一起,极大地提高了Java编程的效率和乐趣。随着时间的流逝,Java开发者对这些特性的理解和应用将会越来越深入,进一步推动Java语言和应用程序的发展。
18 0