深度解析 Java 的 Optional 类(下)

本文涉及的产品
云解析DNS,个人版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 深度解析 Java 的 Optional 类(下)

所以用 ofNullable()newTitle 转换一个 Optional

image.png

  • nullofNullable()返回Optional.empty()
  • 调用 orElseThrow()
  • 1639639428(1).png
  • 如果 newTitle 的值是 null,会得到异常。

这里我们并没有把 title 保存成 Optional,但通过应用 Optional 的功能,我们仍对字段加了约束。

在这个方案里边,你仍然可能会得到一个异常。不同的是,错误产生那刻(向 setTitle() 传 null 值时)就抛异常,而不发生在其它时刻。使用 EmptyTitleException 有助于定位 BUG。

Person 字段的限制:如果把值设 null,程序会自动把将它赋值成一个空的 Person 对象。先前我们也用过类似的方法把字段转换成 Option,但这里我们是在返回结果的时候使用 orElse(new Person()) 插入一个空的 Person 对象替代了 null。


在 Position 里,没有创建一个表示“空”的标志位或者方法,因为 person 字段的 Person 对象为空,就表示这个 Position 是个空位置。之后,你可能会发现你必须添加一个显式的表示“空位”的方法,但是正如 YAGNI (You Aren’t Going to Need It,你永远不需要它)所言,在初稿时“实现尽最大可能的简单”,直到程序在某些方面要求你为其添加一些额外的特性,而不是假设这是必要的。


虽然使用了 Optional,可以免受 NullPointerExceptions,但 Staff 类对此毫不知情。

// typeinfo/Staff.java
import java.util.*;
public class Staff extends ArrayList<Position> {
    public void add(String title, Person person) {
        add(new Position(title, person));
    }
    public void add(String... titles) {
        for (String title : titles)
            add(new Position(title));
    }
    public Staff(String... titles) {
        add(titles);
    }
    public Boolean positionAvailable(String title) {
        for (Position position : this)
            if (position.getTitle().equals(title) &&
                    position.getPerson().empty)
                return true;
        return false;
    }
    public void fillPosition(String title, Person hire) {
        for (Position position : this)
            if (position.getTitle().equals(title) &&
                    position.getPerson().empty) {
                position.setPerson(hire);
                return;
            }
        throw new RuntimeException(
                "Position " + title + " not available");
    }
    public static void main(String[] args) {
        Staff staff = new Staff("President", "CTO",
                "Marketing Manager", "Product Manager",
                "Project Lead", "Software Engineer",
                "Software Engineer", "Software Engineer",
                "Software Engineer", "Test Engineer",
                "Technical Writer");
        staff.fillPosition("President",
                new Person("Me", "Last", "The Top, Lonely At"));
        staff.fillPosition("Project Lead",
                new Person("Janet", "Planner", "The Burbs"));
        if (staff.positionAvailable("Software Engineer"))
            staff.fillPosition("Software Engineer",
                    new Person(
                            "Bob", "Coder", "Bright Light City"));
        System.out.println(staff);
    }
}

输出结果:

[Position: President, Employee: Me Last The Top, Lonely
At, Position: CTO, Employee: <Empty>, Position:
Marketing Manager, Employee: <Empty>, Position: Product
Manager, Employee: <Empty>, Position: Project Lead,
Employee: Janet Planner The Burbs, Position: Software
Engineer, Employee: Bob Coder Bright Light City,
Position: Software Engineer, Employee: <Empty>,
Position: Software Engineer, Employee: <Empty>,
Position: Software Engineer, Employee: <Empty>,
Position: Test Engineer, Employee: <Empty>, Position:
Technical Writer, Employee: <Empty>]

有些地方你可能还是要测试引用是不是 Optional,这跟检查是否为 null 没什么不同。但是在其它地方(例如本例中的 toString() 转换),你就不必执行额外的测试了,而可以直接假设所有对象都是有效的。

标记接口

有时使用标记接口表示空值更方便,把它的名字当做标签来用即可

image.png

用接口取代具体类,即可使用 DynamicProxy 自动创建 Null 对象。

假设有一个 Robot 接口

image.png

Operation 包含一个描述和一个命令(这用到了命令模式)。

定义成函数式接口的引用,所以可以把 lambda 表达式或者方法的引用传给 Operation 的构造器:

image.png

现在我们可以创建一个扫雪 Robot

image.png

假设许多不同类型的 Robot,想让每种 Robot 都创建一个 Null 对象来执行一些特殊的操作

本例中,提供 Null 对象所代表 Robot 的确切类型信息。这些信息是通过动态代理捕获的:

image.png

如果你需要一个空 Robot 对象,只需调用 newNullRobot(),并传递需要代理的 Robot 类型。这个代理满足了 RobotNull 接口的需要,并提供了它所代理的类型的确切名字。

目录
相关文章
|
23小时前
|
自然语言处理 Java 测试技术
Java中的行为驱动开发(BDD)方法论解析
Java中的行为驱动开发(BDD)方法论解析
|
1天前
|
Java
类信息的“隐形守护者”:JAVA反射技术全揭秘
【7月更文挑战第1天】Java反射技术是动态获取类信息并操作对象的强大工具。它基于Class对象,允许在运行时创建对象、调用方法和改变字段。例如,通过`Class.forName()`动态实例化对象,`getMethod()`调用方法。然而,反射可能破坏封装,影响性能,并需处理异常,故使用时需谨慎。它是Java灵活性的关键,常见于框架设计中。
6 0
|
1天前
|
消息中间件 Java API
解析Java微服务架构:从零构建高性能系统
解析Java微服务架构:从零构建高性能系统
|
1天前
|
XML 缓存 JavaScript
优化Java中的XML解析性能
优化Java中的XML解析性能
|
1天前
|
Java 容器
Java中使用Optional类的建议
Java中使用Optional类的建议
|
1天前
|
Java
解析Java中的反射机制应用
解析Java中的反射机制应用
|
1天前
|
存储 安全 Java
Java详解 : 单列集合 | 双列集合 | Collections类
Java详解 : 单列集合 | 双列集合 | Collections类
|
安全 Java
JAVA8实战 - Optional工具类(下)
JAVA8实战 - Optional工具类(下)
606 0
|
JSON 安全 Java
JAVA8实战 - Optional工具类(上)
JAVA8实战 - Optional工具类(上)
208 0
|
1天前
|
安全 Java
Java多线程编程实践中的常见问题与解决方案
Java多线程编程实践中的常见问题与解决方案

推荐镜像

更多