深度解析 Java 的 Optional 类(上)

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

使用内置的 null 来表示没有对象,每次使用引用的时候就必须测试一下引用是否为 null,这显得有点枯燥,而且势必会产生相当乏味的代码。


null 没啥行为,只会产生 NullPointException。

java.util.Optional为 null 值提供了一个轻量级代理,Optional 对象可以防止你的代码抛 NullPointException。


虽然 Optional 是 Java 8 为了支持流式编程才引入的,但其实它是一个通用的工具。实际上,在所有地方都使用 Optional 是没有意义的,有时候检查一下是不是 null 也挺好的,或者有时我们可以合理地假设不会出现 null,甚至有时候检查 NullPointException 异常也是可以接受的。


Optional 最有用武之地的是在那些“更接近数据”的地方,在问题空间中代表实体的对象上。

举个简单的例子,很多系统中都有 Person 类型,代码中有些情况下你可能没有一个实际的 Person 对象(或者可能有,但是你还没用关于那个人的所有信息)。这时,在传统方法下,你会用到一个 null 引用,并且在使用的时候测试它是不是 null。而现在,我们可以使用 Optional:

image.png

输出结果:

<Empty>
Smith
Bob Smith
Bob Smith 11 Degree Lane, Frostbite Falls, MN

Person 的设计有时候叫“数据传输对象(DTO,data-transfer object)”。

所有字段都是 public final ,所以无 getter 和 setter 方法。即Person 不可变,只能通过构造器赋值,只能读而不能修改值。

想修改一个 Person,只能用一个新的 Person 对象来替换它。

empty 字段在对象创建的时候被赋值,用于快速判断这个 Person 对象是不是空对象。


想使用 Person,就必须使用 Optional 接口才能访问它的 String 字段,就不会意外触发 NPE。


可将 Person Optional 对象放在每个 Position 上:

class EmptyTitleException extends RuntimeException {
}
class Position {
    private String title;
    private Person person;
    Position(String jobTitle, Person employee) {
        setTitle(jobTitle);
        setPerson(employee);
    }
    Position(String jobTitle) {
        this(jobTitle, null);
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String newTitle) {
        // Throws EmptyTitleException if newTitle is null:
        title = Optional.ofNullable(newTitle)
                .orElseThrow(EmptyTitleException::new);
    }
    public Person getPerson() {
        return person;
    }
    public void setPerson(Person newPerson) {
        // Uses empty Person if newPerson is null:
        person = Optional.ofNullable(newPerson)
                .orElse(new Person());
    }
    @Override
    public String toString() {
        return "Position: " + title +
                ", Employee: " + person;
    }
    public static void main(String[] args) {
        System.out.println(new Position("CEO"));
        System.out.println(new Position("Programmer",
                new Person("Arthur", "Fonzarelli")));
        try {
            new Position(null);
        } catch (Exception e) {
            System.out.println("caught " + e);
        }
    }
}

输出结果:

Position: CEO, Employee: <Empty>
Position: Programmer, Employee: Arthur Fonzarelli
caught EmptyTitleException

title 和 person 都是普通字段,修改唯一途径是调用 setTitle()、setPerson() ,都借助 Optional 对字段限制。

想保证 title 字段不会成 null,在 setTitle()检查参数值。但其实还有更好的做法,函数式编程一大优势就是可以让我们重用经过验证的功能,以减少自己手动编写代码可能产生的一些小错误。


目录
相关文章
|
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中多态的实现原理解析
Java中多态的实现原理解析
|
1天前
|
Java 容器
Java中使用Optional类的建议
Java中使用Optional类的建议
|
1天前
|
Java
解析Java中的反射机制应用
解析Java中的反射机制应用
|
23小时前
|
并行计算 Java 大数据
Java中的高效并行计算与多线程编程技术
Java中的高效并行计算与多线程编程技术
|
1天前
|
算法 安全 Java
Java小白教学—五千字带你了解多线程机制及线程安全问题
Java小白教学—五千字带你了解多线程机制及线程安全问题
|
1天前
|
安全 Java
解决Java中多线程同步问题的方案
解决Java中多线程同步问题的方案

推荐镜像

更多