繁体   English   中英

空对象设计模式Vs null对象检查

[英]Null object design pattern Vs null object check

为什么null对象设计模式优于null对象检查。 如果我们在null对象设计模式中查看内存占用,我们将创建一个相同类型的新虚拟对象。 如果我们在搜索查询中有大对象和大量可空对象的对象,则该模式将创建大量空对象,这将占用比简单检查更多的内存,对于null,我的成本可忽略的性能延迟。

空对象设计模式

null的整个问题是,如果您尝试访问null值,应用程序将抛出NullPointerException并中止。

要减少此null对象设计模式中的类NullXXX的数量(实际上只是工厂设计数据,而不是模式本身),您可以创建一个始终返回的static final NullCustomer

在Java 8中,您可以使用Optional方法来判断函数何时不总是返回值。 这种方法不会强制您创建污染整体结构的任意空类(考虑可能也必须重构这些空类)。

EclipseIntelliJ还提供编译时注释@Nullable@NonNull @Nullable ,它在访问潜在的null对象时给出编译器警告。 但是,许多框架没有注释。 因此,IntelliJ尝试使用静态分析发现那些潜在的空访问 除了采用这种方法之外,IntelliJ和Eclipse使用自己的注释( org.eclipse.jdt.annotation.NonNullcom.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM