Java getter和setter方法中的Optional,用户希望在访问器(accessor)和更改器(mutator)中使用 Optional,在 Optional 中包装 getter 方法的结果,但不要对 setter 方法,尤其是特性(attribute)执行同样的操作。
Java getter和setter方法中的Optional 问题描述
用户希望在访问器(accessor)和更改器(mutator)中使用 Optional。
Java getter和setter方法中的Optional 解决方案
在 Optional 中包装 getter 方法的结果,但不要对 setter 方法,尤其是特性(attribute)执行同样的操作。
Java getter和setter方法中的Optional 具体实例
在 Optional 数据类型与用户通信的过程中,操作结果可以合法为 null 而不会抛出 NullPointerException。但是,Optional 类被有意设计成不可序列化(non-serializable),所以不应使用它来包装类中的字段。
因此,在 getter 和 setter 方法中添加 Optional 的首选方案,是当 getter 返回时在其中包装可空特性(nullable attribute),但不要对 setter 执行同样的操作。相关示例如例 6-12 所示。
例 6-12 在 DAO(数据访问对象)层中使用
Optional
public class Department {
private Manager boss;
public Optional<Manager> getBoss() {
return Optional.ofNullable(boss);
}
public void setBoss(Manager boss) {
this.boss = boss;
}
}
在本例中,boss 是 Department 类中的 Manager 特性,可以将其视为可空类型 4。用户或许试图创建类型为 Optional<Manager> 的特性,但由于 Optional 不可序列化,Department 也不可序列化。
4或许这是个一厢情愿但颇具吸引力的想法。
本例不要求用户包装 Optional 中的值以调用 setter 方法,但这是 setBoss 方法传入 Optional<Manager> 作为参数所必需的。Optional 用于表示一个可能合法为 null 的值,且客户端已经了解该值是否为 null,但内部实现并不关心该值是否为 null。
此外,在 getter 方法中返回 Optional<Manager> 将告知调用程序,此时 Department 可能有(也可能没有)boss。
本例的不足之处在于,多年以来,“JavaBeans”规范基于特性“对称”地定义了 getter 和 setter。实际上,Java 将属性(property)——而不仅仅是特性(attribute)——定义为遵循标准模式的 getter 和 setter。而本范例讨论的方案违反了这种模式,getter 和 setter 不再是对称的。
有鉴于此,部分开发人员认为 getter 和 setter 方法中不应出现 Optional,它属于不应暴露给客户端的内部实现细节。
不过,本范例讨论的方案被使用 Hibernate 等 ORM(对象关系映射)工具的开源开发者所广泛接受。首要问题是告知客户端,存在一个支持特定字段的可空数据库列(nullable database column),而不必强制客户端在 setter 方法中包装引用。这似乎是一种合理的折中方案,但正如这些开发者所言,解决方案应根据具体情况而定。
极客教程