空对象设计模式与空对象检查
Null object design pattern Vs null object check
为什么空对象设计模式优于空对象检查。
如果我们查看空对象设计模式中的内存占用,我们会创建一个新的相同类型的虚拟对象。这表明如果我们在搜索查询中有大尺寸的对象和大量可为空的对象,这种模式将创建那么多的空对象,这将比简单的检查占用更多的内存,对于 null,我的性能成本可以忽略不计。
这种模式的主要区别(也可能是优点)是独特性。考虑以下方法定义:
public static int length(String str);
此方法计算给定字符串的长度。但是参数可以是 null
吗?该方法将做什么?抛出异常? Return0? Return-1?我们不知道。
一些部分解决方案可以通过编写好的 java 文档来实现。下一个更好的解决方案是使用注释 JSR305 注释 @Nullable
或 @NotNullable
,但是开发人员可以忽略这些注释。
如果您使用空对象模式(例如番石榴或 java8 的可选),您的代码如下所示:
public static int length(Optional<String> str);
因此开发人员必须关心将他的字符串包装到 Optional 中,因此了解参数可以为 null。尝试从包含 null 的 Optional 中获取值会导致在使用常规 null
时并不总是发生的异常。
显然您是对的,使用此模式会导致一些额外的 CPU 和内存消耗,但在大多数情况下并不显着。
使用空对象而不是 null
的主要优点是使用 null
您必须 重复 检查该对象是否确实 null
,特别是在所有需要该对象的方法中。
在Java8中,需要做的是:
Object o = Objects.requireNotNull(o); //Throws NullPointerException if o is indeed null.
因此,如果您有一个不断将同一个对象传递给各种方法的方法,则每个方法在使用之前都需要检查接收到的对象是否为空。
因此,更好的方法是使用空对象,或 Optional
(Java 8 及更高版本),这样您就不需要一直进行空检查。取而代之的是:
Object o = optional.get(); //Throws NullPointerException if internal value is indeed null.
//Keep using o.
不需要(真的)进行空值检查。你有一个 Optional
的事实意味着你可能有一个值或 none.
Null 对象没有副作用,因为它通常什么都不做(通常所有方法都是空方法)所以不用担心性能问题(bottlenecks/optimization/etc ).
null
的全部问题在于,如果您尝试访问 null
值,应用程序将抛出 NullPointerException
并中止。
在这个空对象设计模式中减少classNullXXX
的数量(它实际上只是工厂设计模式,而不是模式本身)你可以做一个 static final NullCustomer
总是 returned.
在 Java 8 中,您可以使用 Optional 方法来判断函数何时不总是 return 值。这种方法不会强制您创建任意 null classes 来污染整体结构(考虑可能也必须重构那些 null classes)。
Eclipse and IntelliJ also offer compile time annotations @Nullable
, @NonNull
which give compiler warnings when accessing potential null
objects. However, many frameworks are not annotated. IntelliJ therefore tries to discover those potential null accesses 静态分析。
除了这种方法的低采用率之外,IntelliJ 和 Eclipse 使用它们自己的不兼容的注释(org.eclipse.jdt.annotation.NonNull
、com.intellij.annotations.NotNull
)。但是,您可以 store the annotations outside of the code which works in IntelliJ. Eclipse want to implement this in the future, too. The problem is that there are many frameworks providing this feature giving you many different annotations doing the very same. There was JSR-305 处于休眠状态。它会在 javax
中提供注释。我不知道他们为什么没有进一步推动这一点。
假设你有这样的事情:
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 对象与空(无操作)方法一起使用,我们避免了样板空值检查(以及忘记为所有事件添加检查的可能性)。
我经常发现这在异步或可选初始化某些东西的情况下很有用。
为什么空对象设计模式优于空对象检查。 如果我们查看空对象设计模式中的内存占用,我们会创建一个新的相同类型的虚拟对象。这表明如果我们在搜索查询中有大尺寸的对象和大量可为空的对象,这种模式将创建那么多的空对象,这将比简单的检查占用更多的内存,对于 null,我的性能成本可以忽略不计。
这种模式的主要区别(也可能是优点)是独特性。考虑以下方法定义:
public static int length(String str);
此方法计算给定字符串的长度。但是参数可以是 null
吗?该方法将做什么?抛出异常? Return0? Return-1?我们不知道。
一些部分解决方案可以通过编写好的 java 文档来实现。下一个更好的解决方案是使用注释 JSR305 注释 @Nullable
或 @NotNullable
,但是开发人员可以忽略这些注释。
如果您使用空对象模式(例如番石榴或 java8 的可选),您的代码如下所示:
public static int length(Optional<String> str);
因此开发人员必须关心将他的字符串包装到 Optional 中,因此了解参数可以为 null。尝试从包含 null 的 Optional 中获取值会导致在使用常规 null
时并不总是发生的异常。
显然您是对的,使用此模式会导致一些额外的 CPU 和内存消耗,但在大多数情况下并不显着。
使用空对象而不是 null
的主要优点是使用 null
您必须 重复 检查该对象是否确实 null
,特别是在所有需要该对象的方法中。
在Java8中,需要做的是:
Object o = Objects.requireNotNull(o); //Throws NullPointerException if o is indeed null.
因此,如果您有一个不断将同一个对象传递给各种方法的方法,则每个方法在使用之前都需要检查接收到的对象是否为空。
因此,更好的方法是使用空对象,或 Optional
(Java 8 及更高版本),这样您就不需要一直进行空检查。取而代之的是:
Object o = optional.get(); //Throws NullPointerException if internal value is indeed null.
//Keep using o.
不需要(真的)进行空值检查。你有一个 Optional
的事实意味着你可能有一个值或 none.
Null 对象没有副作用,因为它通常什么都不做(通常所有方法都是空方法)所以不用担心性能问题(bottlenecks/optimization/etc ).
null
的全部问题在于,如果您尝试访问 null
值,应用程序将抛出 NullPointerException
并中止。
在这个空对象设计模式中减少classNullXXX
的数量(它实际上只是工厂设计模式,而不是模式本身)你可以做一个 static final NullCustomer
总是 returned.
在 Java 8 中,您可以使用 Optional 方法来判断函数何时不总是 return 值。这种方法不会强制您创建任意 null classes 来污染整体结构(考虑可能也必须重构那些 null classes)。
Eclipse and IntelliJ also offer compile time annotations @Nullable
, @NonNull
which give compiler warnings when accessing potential null
objects. However, many frameworks are not annotated. IntelliJ therefore tries to discover those potential null accesses 静态分析。
除了这种方法的低采用率之外,IntelliJ 和 Eclipse 使用它们自己的不兼容的注释(org.eclipse.jdt.annotation.NonNull
、com.intellij.annotations.NotNull
)。但是,您可以 store the annotations outside of the code which works in IntelliJ. Eclipse want to implement this in the future, too. The problem is that there are many frameworks providing this feature giving you many different annotations doing the very same. There was JSR-305 处于休眠状态。它会在 javax
中提供注释。我不知道他们为什么没有进一步推动这一点。
假设你有这样的事情:
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 对象与空(无操作)方法一起使用,我们避免了样板空值检查(以及忘记为所有事件添加检查的可能性)。
我经常发现这在异步或可选初始化某些东西的情况下很有用。