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

时间:2015-08-26 06:37:01

标签: java design-patterns conditional-statements nullable

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

Null Object design pattern

4 个答案:

答案 0 :(得分:6)

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

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

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

EclipseIntelliJ还提供编译时注释@Nullable@NonNull,在访问潜在的null对象时会给出编译器警告。但是,许多框架没有注释。因此,IntelliJ尝试使用静态分析discover those potential null accesses。 除了采用这种方法之外,IntelliJ和Eclipse使用自己的注释(org.eclipse.jdt.annotation.NonNullcom.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对象与空(无操作)方法一起使用,我们避免了样板空检查(并且可能忘记为所有出现添加检查)。

在异步或可选地初始化某些内容时,我经常发现这很有用。