Java优雅解决空指针问题源码级别刨析Optional 2

简介: Java优雅解决空指针问题源码级别刨析Optional

2.2.5 flatMap()应用&源码解析

刚才已经通过map()获取了学生的姓名,操作非常简单。但是当产生链路获取时,map可以使用么?

如:学生->工作->公司->公司名称。现在可能大家脑袋里已经有了一个想法,就是通过map(),代

码结构如下:

studentOptional.map(Student::getJob).map(Job:
:getCompany).map(Company::getName);

但是这段代码是无法通过编译的。因为根据map的学习,每一次在调用的时候,都会对Optional的泛型进行改变,最终产生多层Optional嵌套的结构。如下图所示:

aa3ead5980974f6abb0f8b3ac1e7bef0.png

对于这个问题的解决,Optional类中提供了另外一个获取值的方法flatMap()。它本身用于多层调用,同时对于结果它不会形成多个Optional,而是将结果处理成最终的一个类型的Optional。但是通过flatMap获取的返回值必须是Optional类型。而map则没有这个限制。

2db388d1d0c24b04aeda30061a8fd901.png

使用示例如下:

Optional<String> nameOptional =
studentOptional.flatMap(Student::getJob).flat
Map(Job::getCompany).map(Company::getName);

2.2.6 filter()应用&源码解析

在获取某个对象中的属性值时,经常会根据特定的条件进行获取。之前的编码方法通常为:

Company company = optional().get();
if("oldlu".equals(company.getName)){
  sout(company);
}

Optional类中也提供了数据过滤的方法filter()来实现这个需求。其会根据传入的条件进行判断,如果匹配则返回一个Optional对象并包含对应的值,否则返回一个空值的Optional

使用示例如下:

Optional<Company> company =
companyOptional.filter(c ->
"oldlu".equals(c.getName()));

2.2.7 orElse()应用&源码解析

在取值的时候,如果值不存在,有时我们会考虑返回一个默认值。该需求就可以通过orElse()实现。

其内部会判断值是否为null,如果不为null,则返回该值,如果为null,则返回传入的默认值。

使用示例如下:

public class Demo1 {
  public static void
getCompanyName(Student student) {
    Optional<Student> studentOptional =
Optional.ofNullable(student);
    if (studentOptional.isPresent()) {
       String value =
studentOptional.flatMap(Student::getJob).fla
tMap(Job::getCompany).map(Company::getName).
orElse("default value");
      System.out.println(value);
   }
 }
  public static void main(String[] args) {
    Company company = new Company();
    //company.setName("oldlu");
    Optional<Company> companyOptional =
Optional.of(company);
    Job job = new Job();
    job.setName("pm");
    job.setCompany(companyOptional);
    Optional<Job> jobOptional =
Optional.of(job);
    Student s1 = new Student();
    s1.setName("张三");
    s1.setJob(jobOptional);
    getCompanyName(s1);
 }
 }

2.2.8 orElseGet()应用&源码解析

orElseGet()也是用于当Optional中没有值时,返回默认值的方法。但是它与orElse()的区别在于,它是延迟加载的。只有当Optional中没有值是才会被调用。

区别示例如下:

1)当公司名称不存在

public class Demo1 {
  public static void
getCompanyName(Student student) {
    Optional<Student> studentOptional =
Optional.ofNullable(student);
    if (studentOptional.isPresent()) {
      String value1 =
studentOptional.flatMap(Student::getJob).fla
tMap(Job::getCompany).map(Company::getName).
orElse(get("a"));
      String value2 =
studentOptional.flatMap(Student::getJob).fla
tMap(Job::getCompany).map(Company::getName).
orElseGet(()->get("b"));
      System.out.println("a: 
"+value1);
      System.out.println("b: 
"+value2);
   }
 }
  public static String get(String name) {
    System.out.println(name + "执行了方
法");
    return "exec";
 }
  public static void main(String[] args) {
    Company company = new Company();
    //company.setName("oldlu");
    Optional<Company> companyOptional =
Optional.of(company);
    Job job = new Job();
    job.setName("pm");
    job.setCompany(companyOptional);
    Optional<Job> jobOptional =
Optional.of(job);
    Student s1 = new Student();
s1.setName("张三");
    s1.setJob(jobOptional);
    getCompanyName(s1);
 }
}

执行结果

a执行了方法
b执行了方法
a:  exec
b:  exec


根据上述结果可知,当公司名称不存在时,orElse()与orElseGet()都被执行了。

2)公司名称存在

public class Demo1 {
  public static void
getCompanyName(Student student) {
    Optional<Student> studentOptional =
Optional.ofNullable(student);
    if (studentOptional.isPresent()) {
      String value1 =
studentOptional.flatMap(Student::getJob).fla
tMap(Job::getCompany).map(Company::getName).
orElse(get("a"));
      String value2 =
studentOptional.flatMap(Student::getJob).fla
tMap(Job::getCompany).map(Company::getName).
orElseGet(()->get("b"));
      System.out.println("a: 
"+value1);
      System.out.println("b: 
"+value2);
   }
 }
  public static String get(String name) {
    System.out.println(name + "执行了方
法");
    return "exec";
 }
  public static void main(String[] args) {
    Company company = new Company();
    company.setName("oldlu");
    Optional<Company> companyOptional =
Optional.of(company);
    Job job = new Job();
    job.setName("pm");
    job.setCompany(companyOptional);
    Optional<Job> jobOptional =
Optional.of(job);
    Student s1 = new Student();
    s1.setName("张三");
    s1.setJob(jobOptional);
    getCompanyName(s1);
 }
}

执行结果如下:

a执行了方法
a:  oldlu
b:  oldlu
目录
相关文章
|
2月前
|
安全 Java 开发者
告别NullPointerException:拥抱Java Optional
告别NullPointerException:拥抱Java Optional
|
1月前
|
安全 Java 容器
告别繁琐判空:Optional让你的Java代码更优雅
告别繁琐判空:Optional让你的Java代码更优雅
|
1月前
|
安全 Java 容器
告别空指针噩梦:Optional让Java代码更优雅
告别空指针噩梦:Optional让Java代码更优雅
347 94
|
1月前
|
安全 Java 开发者
告别NullPointerException:掌握Java Optional的精髓
告别NullPointerException:掌握Java Optional的精髓
|
2月前
|
存储 小程序 Java
热门小程序源码合集:微信抖音小程序源码支持PHP/Java/uni-app完整项目实践指南
小程序已成为企业获客与开发者创业的重要载体。本文详解PHP、Java、uni-app三大技术栈在电商、工具、服务类小程序中的源码应用,提供从开发到部署的全流程指南,并分享选型避坑与商业化落地策略,助力开发者高效构建稳定可扩展项目。
|
4月前
|
存储 人工智能 Java
Java 8 的 Optional:提高代码安全性与可读性
本文深入解析 Java 中的 `NullPointerException` 及其传统处理方式,并介绍了 Java 8 引入的 `Optional` 类。通过示例代码讲解了 `Optional` 的创建、使用及其 API,探讨了其在实际开发中的最佳实践与局限性,帮助开发者提升代码的健壮性与可读性。
108 0
Java 8 的 Optional:提高代码安全性与可读性
|
6月前
|
JavaScript Java 关系型数据库
家政系统源码,java版本
这是一款基于SpringBoot后端框架、MySQL数据库及Uniapp移动端开发的家政预约上门服务系统。
211 6
家政系统源码,java版本
|
6月前
|
供应链 JavaScript 前端开发
Java基于SaaS模式多租户ERP系统源码
ERP,全称 Enterprise Resource Planning 即企业资源计划。是一种集成化的管理软件系统,它通过信息技术手段,将企业的各个业务流程和资源管理进行整合,以提高企业的运营效率和管理水平,它是一种先进的企业管理理念和信息化管理系统。 适用于小微企业的 SaaS模式多租户ERP管理系统, 采用最新的技术栈开发, 让企业简单上云。专注于小微企业的应用需求,如企业基本的进销存、询价,报价, 采购、销售、MRP生产制造、品质管理、仓库库存管理、财务应收付款, OA办公单据、CRM等。
405 23
|
5月前
|
存储 安全 Java
Java 集合面试题从数据结构到 HashMap 源码剖析详解及长尾考点梳理
本文深入解析Java集合框架,涵盖基础概念、常见集合类型及HashMap的底层数据结构与源码实现。从Collection、Map到Iterator接口,逐一剖析其特性与应用场景。重点解读HashMap在JDK1.7与1.8中的数据结构演变,包括数组+链表+红黑树优化,以及put方法和扩容机制的实现细节。结合订单管理与用户权限管理等实际案例,展示集合框架的应用价值,助你全面掌握相关知识,轻松应对面试与开发需求。
292 3
|
安全 Java
Java并发编程笔记之CopyOnWriteArrayList源码分析
并发包中并发List只有CopyOnWriteArrayList这一个,CopyOnWriteArrayList是一个线程安全的ArrayList,对其进行修改操作和元素迭代操作都是在底层创建一个拷贝数组(快照)上进行的,也就是写时拷贝策略。
19646 0

热门文章

最新文章