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 方法中包装引用。这似乎是一种合理的折中方案,但正如这些开发者所言,解决方案应根据具体情况而定。