2012-07-26 52 views
2

在将类嵌入为其他类的属性的常见情形中,检查空值的最佳方法是什么?在访问属性属性的属性时,检查空值的正确方法是什么?

为了说明我在说什么,说我想访问this.getObject1().getObject2().someMethod()其中getObject1()getObject2()可能会返回null。现在我做了以下内容,它的丑陋,并必须有一个更好的办法:

if (this.getObject1() != null) 
     if (this.getObject1().getObject2() != null) 
      if (this.getObject1().getObject2().someMethod()) 
       return whatever; 

为了避免NPE,我必须在每一个步骤访问的someMethod之前检查空值()。什么是更好的方法来完成这个?

+0

虽然不是100%相关,但您可能需要考虑阅读空对象模式,因为它可能与您的代码有某些关联。 http://en.wikipedia.org/wiki/Null_Object_pattern#Java – BlackVegetable 2012-07-26 21:15:39

+0

尽量避免这种风格 - 请参阅http://pragprog.com/articles/tell-dont-ask - 虽然我很欣赏那个库或遗留代码可能不会给你太多的选择...... – DNA 2012-07-26 21:40:46

+0

在方法调用前你不需要'this.'。 – 2012-07-26 21:48:59

回答

1

这种风格是尽量要避免的 - 看到Law of Demeter - 尽管我明白,库或遗留代码可能不会离开你太多的选择。

函数式编程语言(尤其是)通过使用OptionMaybe对象来避免此问题,它可以在某种程度上在Java中使用。例如,请参阅this article。对于eaxmple,可以使用Scala for-comprehensions简洁地避免长序列的空检查。但回到Java ...

理想情况下,假设你可以修改你调用的代码,你会重组,所以你可以调用'外部'对象,然后调用'内部'对象,只有一个null在每个阶段检查。或者重构代码以避免这种深层嵌套。

+0

我喜欢“告诉,不要问”的概念,但我会记住,但为了避免NPE,在访问该属性的属性之前,您必须询问该对象的属性是否为空,对吗?如果对象为空,则无法“让对象处理它”。 – 2012-07-27 12:34:21

+1

一种方法是创建一个您存储的特殊“空对象”,而不是实际的空值。换句话说,您有一个超类或接口,带有一个或多个“真实”子类,以及一个可以安全响应调用的特例“空子类”。 – DNA 2012-07-27 12:55:37

3

另一种方法是将每种方法的结果设置为变量,以便您不必每次都重新调用该方法。所以,像这样

Object obj1 = this.getObject1(); 
if (null != obj1) 
{ 
    Object obj2 = obj1.getObject2(); 
    if (null != ob2) 
    { 
     Object obj3 = obj2.someMethod(); 
     if (null != obj3) 
       return whatever; 
    } 
} 

如果方法不贵,你可以做这一切一样if内像克里斯·纳瓦的解决方案选择更少的代码

+0

这可能是一个改进(虽然答案可能措辞得更好。)编辑:好得多。 – BlackVegetable 2012-07-26 21:11:44

+0

谢谢你的建议。不过,我不确定这会提高可读性,足以证明额外的代码行。这是一种折腾。 – 2012-07-27 13:02:11

1

你可以把它简化更多(至少更容易阅读)像:

Object o1 = getObject1(); 
if(o1 != null) 
{ 
    Object o2 = getObject2(); 
    if(o2 != null) 
    { 
     if(o2.someMethod()) return whatever; 
    } 
} 
1

真的没有太多的事情可以做。我的意思是,你可以将每一步分配给一个变量,但它最终会成为更多的代码,并且你可以用一个通用的方法来使用反射来完成它,但是它的性能会低得多,因为不是真的好理由。

2

我用& &代替嵌套的if()s。它只是稍微更清洁(可以说),但仍然不是我想要的。

if (
    this.getObject1() != null 
    && 
    this.getObject1().getObject2() != null 
    && 
    this.getObject1().getObject2().someMethod() 
) { 
      return whatever; 
} 
+0

如果获得的对象[相对]廉价和纯粹(因为结果是相同的)..这是我立即倾向于的方法,但我更喜欢在每个'&&' ; - )虽然一般我会尽量避免这种情况.. – 2012-07-26 21:23:39

+0

我同意。上面假设get()查找相对便宜。如果不是,那么嵌套if()的局部变量是更好的选择。我也同意整个情况是一种代码味道。 – 2012-07-26 21:29:51

相关问题