2012-07-20 58 views
4

我已阅读过这个主题:Avoiding != null statements但我没有看到好处。在java中避免!= null的好处是什么?

  1. 如果返回空数组,你需要检查这里的“真实”的阵列,并且其中空数组。

  2. 代替使用getName() != null这样的代码,您必须使用getName().length > 0。作为一个例子,我正在研究项目,在那里我需要用少量归档器压缩一些数据,并决定选择最小尺寸的压缩数据。如果我从归档程序“compress”方法返回null,则需要检查返回的值是否为空。如果我决定返回一个空数组,那么我也需要检查它是否为空。

对吗?

+0

我反对完全避免的东西,除非它被证明是完全不好用。在这种情况下,如果空的数组/列表和空值表示不同的含义,则应该使用空值。如果null和空数组/列表本身并没有传达特殊含义,那么它们可以互换使用,以使代码更清晰。 – nhahtdh 2012-07-20 05:10:59

+0

我不明白你的第一点。什么是“真正的”阵列?如果你返回null,那*应该是真实的数组。如果这是一个错误的情况下,抛出一个异常。 – 2012-07-20 05:18:56

+0

@JakeKing,你看我的例子吗?我有压缩函数,如果那个函数返回空数组,比解压缩函数会失败,因为它的实现,这需要检查它的第一个字节,所以我需要检查这种情况。 – 2012-07-20 05:23:01

回答

11

使用空集合或“空白”动作而不是null的主要优点是大多数情况下,这些对象仍然可以在代码中工作,无需进一步修改。由于其本质,其核心价值观更容易出错。

看看下面的代码,例如:

String[] names = data.getNames(); 
if (names != null) { 
    for (String name : names) { 
     // Do stuff 
    } 
} 

null的检查是必需的,否则你会得到一个NPE。使用循环标准不能解决问题。另一方面,如果你知道你总是会得到一些类型的数组,你的代码将会在的罚款工作,没有额外的检查。如果数组为空,循环将不会运行。问题解决了。

对于实现某种形式的操作的代码也是如此。又如:

Action myAction = data.getActionToRun(); 
if (myAction != null) { 
    myAction.run(); 
} 

再次,你需要一个null检查。如果行动保证存在,那么你总是可以拨打action.run()而没有任何副作用,但空白的行动是不会做任何事情。就这么简单。

在许多情况下,如果修改方法返回的方式,导致更简单易懂的代码,则可以简单地丢弃null检查。在某些情况下,返回null正确的选择(例如,从键和值的集合中获取对象),因为没有默认的“无动作”值。但是null表示根本没有价值,并且它需要额外的处理作为接收者。使用空白的无操作的非空对象允许数据对象处理错误。这是很好的封装。这是很好的编程。它只是工作。™

最后,返回null当然不是处理错误的好方法。如果代码中出现错误,应该不会出现出错,除非您作为程序员犯了编程错误,请使用assert或异常。那些是失败的。不要使用null作为失败案例,将其用作简单的缺乏值。

+0

非常有帮助,谢谢。这意味着在我的示例中,最好在压缩功能无法压缩时添加空数组,列表检查这些数据是不是空的,以避免NPE – 2012-07-20 05:31:25

+2

@AvershinDmitry这不一定是最好的解决方案。这听起来像该方法应该永远不会返回一个空值(或一个空数组),除非有错误。这不是一个好主意。如果出现错误,请改为抛出异常。 – 2012-07-20 06:00:01

7

空数组是一个更自然的对象,有时会返回。考虑像这样的代码:

String [] elements = getElements(); 

for (String element : elements) 
    System.out.println(element); 

如果返回一个空数组(即,没有元素),什么都不会被打印,并且代码将正确执行。但是,如果getElements()返回null,则将获得空指针异常。为了防止它,你需要添加更多的代码,这使事情变得更加复杂。返回一个空数组允许在没有附加代码的情况下发生期望的行为。

+0

是的,这是真的,但正如我在我的例子中提到的,这种方法并不总是正确的 – 2012-07-20 05:10:01

1

我想了一会儿。 暂时搁置NPE问题。我会尝试从面向对象的角度解释我的想法。

假设您编写了一个为Glass实例提供吸气剂的类 public Glass getGlass()。 当我阅读这个签名时,我期待Glass接口的一些实例,null不是一个。

您可以考虑下一个方法public Optional<Glass> getGlass()

可选类(可自己编写或使用Google's guava Optional)包含您的通用类实例,同时提供isPresent函数等。 看起来多余的原因可能只是从您的客户端代码中使用getGlass() != null而不是getGlass().isPresent()。但这里的主要优点是签名很简单。没有人隐藏任何东西,你不必猜测。

所以,你得到的好处:

  1. 避免NPE的
  2. 简单的签名
  3. 干净的客户端代码
相关问题