[英]Null object design pattern Vs null object check
为什么null对象设计模式优于null对象检查。 如果我们在null对象设计模式中查看内存占用,我们将创建一个相同类型的新虚拟对象。 如果我们在搜索查询中有大对象和大量可空对象的对象,则该模式将创建大量空对象,这将占用比简单检查更多的内存,对于null,我的成本可忽略的性能延迟。
null
的整个问题是,如果您尝试访问null
值,应用程序将抛出NullPointerException
并中止。
要减少此null对象设计模式中的类NullXXX
的数量(实际上只是工厂设计数据,而不是模式本身),您可以创建一个始终返回的static final NullCustomer
。
在Java 8中,您可以使用Optional方法来判断函数何时不总是返回值。 这种方法不会强制您创建污染整体结构的任意空类(考虑可能也必须重构这些空类)。
Eclipse和IntelliJ还提供编译时注释@Nullable
, @NonNull
@Nullable
,它在访问潜在的null
对象时给出编译器警告。 但是,许多框架没有注释。 因此,IntelliJ尝试使用静态分析发现那些潜在的空访问 。 除了采用这种方法之外,IntelliJ和Eclipse使用自己的注释( org.eclipse.jdt.annotation.NonNull
, com.intellij.annotations.NotNull
),这些注释不兼容。 但是,您可以将注释存储在IntelliJ中工作的代码之外 。 Eclipse也希望将来实现这一点。 问题是,有许多框架提供此功能,为您提供许多不同的注释。 JSR-305处于休眠状态。 它在javax
提供了一个注释。 我不知道为什么他们没有进一步推动这一点。
使用Null Object而不是null
的主要优点是使用null
您必须重复检查该对象是否确实为null
,特别是在需要该对象的所有方法中。
在Java 8中,必须要做的事情是:
Object o = Objects.requireNotNull(o); //Throws NullPointerException if o is indeed null.
因此,如果您有一个不断将相同对象传递给各种方法的方法,则每个方法都需要在使用之前检查接收到的对象是否为null。
因此,更好的方法是使用Null对象或Optional
(Java 8及更高版本),这样您就不需要一直进行空检查。 相反,人们会:
Object o = optional.get(); //Throws NullPointerException if internal value is indeed null.
//Keep using o.
不(真的)需要空检查。 您拥有Optional
的事实意味着您可能拥有值或没有值。
Null Objects没有副作用,因为它通常什么都不做 (通常所有方法都是空方法)所以不需要担心性能(瓶颈/优化/等)。
这种模式的主要区别(可能是优势)是清晰度。 考虑以下方法定义:
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和内存消耗,但在大多数情况下并不重要。
假设你有这样的东西:
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对象和空(无操作)方法,我们避免了样板空检查(并且忘记为所有事件添加检查的可能性)。
在异步或可选地初始化某些内容时,我经常发现这很有用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.