在java中,我们更喜欢null object
模式,而不是在所有引用中使用非null检查来混淆代码。最近,我们遇到了一个问题,即通过保留null object
对象来使用singleton
。
假设我们有Person
类,如下所示
public class Person {
public String firstName;
public String lastName;
public boolean isNull() {
return false;
}
public static final Person NULL = new Person() {
public boolean isNull() { return true; }
}
}
在这种情况下,虽然我已将NULL
对象声明为final,但我仍然可以修改成员变量及其全局可用。
Person nullRef = Person.NULL;
Person.NULL.firstName = "sample";
System.out.println(nullRef.firstName);
在这种情况下,它只有三个字段,我可以通过覆盖这三个getter方法来解决可变性问题。但实际上会有很多字段难以覆盖所有相应的getter方法。
是否有任何标准模式或策略来解决NULL
对象中的可变性问题?
答案 0 :(得分:2)
使用Google Guava库中的Optional
Optional<Integer> possible = Optional.of(5);
possible.isPresent(); // returns true
possible.get(); // returns 5
引用图书馆文档:
除了提供null a的可读性增加之外 名称,Optional的最大优点是它的白痴证明
这是处理空对象的更自然的方式
答案 1 :(得分:1)
你需要有两个级别的接口:一个用于不可变部分(只有getter和immutable方法),另一个用于扩展不可变接口的可变部分。然后需要对代码进行重构,以便仅在所有相关位置使用最严格的接口。
所以
public interface ImmutablePerson {
final String getFirstName();
}
public interface MutablePerson extends ImmutablePerson {
final void setLastName(final String newName);
}
是的,现在MutablePerson“是一个”ImmutablePerson,但只在用作一个时:)
此外,isNull检查表明您需要更多地考虑控制反转。
具体:
当你发现自己编写像
这样的代码时if (!person.isNull()) {
person.setLastName("Foo");
}
你应该只使用你的Null对象并将其视为一个中性元素。像这样:
首先:
final Person NullPerson = new Person() {
void setLastName(final String newName) {
// Do nothing, this is a neutral (Null) object
}
}
......然后是:
// Never need to check for isNull ever again - null objects just decide to ignore your request
person.setLastName("Foo");
答案 2 :(得分:0)
您需要修改“setter”方法而不是getter方法,以使其不可变。 例如。
public String setFirstName(String name){ 如果(!ISNULL()){ firstName = name; } }