为什么空对象设计模式优于空对象检查。 如果我们在null对象设计模式中查看内存占用,我们将创建一个相同类型的新虚拟对象。如果我们在搜索查询中有大对象和大量可空对象的对象,则该模式将创建大量空对象,这将占用比简单检查更多的内存,对于null,我的成本可忽略的性能延迟。 / p>
答案 0 :(得分:6)
null
的整个问题是,如果您尝试访问null
值,应用程序将抛出NullPointerException
并中止。
要减少此 null对象设计模式中的类NullXXX
的数量(实际上只是工厂设计数据,而不是模式本身),您可以创建static final NullCustomer
总是返回。
在Java 8中,您可以使用Optional方法来判断函数何时不总是返回值。这种方法不会强制您创建污染整体结构的任意空类(考虑可能也必须重构这些空类)。
Eclipse和IntelliJ还提供编译时注释@Nullable
,@NonNull
,在访问潜在的null
对象时会给出编译器警告。但是,许多框架没有注释。因此,IntelliJ尝试使用静态分析discover those potential null accesses。
除了采用这种方法之外,IntelliJ和Eclipse使用自己的注释(org.eclipse.jdt.annotation.NonNull
,com.intellij.annotations.NotNull
),这些注释不兼容。但是,你可以在IntelliJ中使用store the annotations outside of the code。 Eclipse也希望将来实现这一点。问题是有many frameworks providing this feature给你许多不同的注释做同样的事情。有JSR-305处于休眠状态。它在javax
中提供了注释。我不知道为什么他们没有进一步推动这一点。
答案 1 :(得分:1)
使用Null Object而不是null
的主要优点是使用null
您必须重复检查该对象是否确实null
,特别是在所有需要该对象的方法中。
在Java 8中,必须要做:
Object o = Objects.requireNotNull(o); //Throws NullPointerException if o is indeed null.
因此,如果你有一个方法不断将同一个对象传递给各种方法,每个方法都需要在使用之前检查收到的对象是否为空。
因此,更好的方法是使用Null对象,或Optional
(Java 8及更高版本),这样您就不需要一直进行空检查。相反,人们会:
Object o = optional.get(); //Throws NullPointerException if internal value is indeed null.
//Keep using o.
没有(真的)需要空检查。您拥有Optional
这一事实意味着您可能拥有值或无值。
Null Objects没有副作用,因为它通常 nothing (通常所有方法都是空方法)所以不需要担心性能(瓶颈/优化/等)。
答案 2 :(得分:0)
这种模式的主要区别(可能是优势)是清晰度。考虑以下方法定义:
public static int length(String str);
此方法计算给定字符串的长度。但争论可能是null
吗?这个方法会做什么?抛出异常?返回0?返回-1?我们不知道。
通过编写好的java doc可以实现一些部分解决方案。下一个更好的解决方案是使用注释JSR305 annotattion @Nullable
或@NotNullable
然而开发人员可以忽略它。
但是,如果您使用Null对象模式(例如guava或java 8的可选),则代码如下所示:
public static int length(Optional<String> str);
因此开发人员必须关心将其字符串包装到Optional中,因此理解该参数可以为null。尝试从包含null的Optional获取值会导致在使用常规null
时并非总是会发生异常。
显然你是对的,使用这种模式会导致一些额外的CPU和内存消耗,但在大多数情况下并不重要。
答案 3 :(得分:0)
假设你有类似的东西:
private SomeClass someField;
void someMethod() {
// some other code
someField.method1();
// some other code
someField.method2();
// some other code
someField.method3();
}
现在假设当someField
可以是null
并且您不想调用其方法但是您想要执行其他some other code
部分时,存在有效用例方法。您需要将该方法实现为:
void someMethod() {
// do something
if (someField != null) {
someField.method1();
}
// do something
if (someField != null) {
someField.method2();
}
// do something
if (someField != null) {
someField.method3();
}
}
通过将Null对象与空(无操作)方法一起使用,我们避免了样板空检查(并且可能忘记为所有出现添加检查)。
在异步或可选地初始化某些内容时,我经常发现这很有用。