使用与避免NULL值
“Null sucks.” -Doug Lea
“I call it my billion-dollar mistake.” - Sir C. A. R. Hoare, on his invention of the null reference
粗心使用null可能会导致各种错误。Google代码库大约95%的集合类中不支持存储null值,而让它们快速失败而不是静默接受null,这样做法对开发人员有所帮助。
此外,null值本身代表的含义会造成歧义。使用null以外的内容可以使您的意思清楚。
有时候使用null却是正确的选择。就内存和速度而言,null使用起来资源消耗低,并且在对象数组中不可避免使用null。但是在应用程序代码中,null是导致bug和歧义的主要来源。
由于以上这些原因,Guava的许多工具类都被设计为在存在null的情况下快速失败,而不是允许使用null,除非有可用的null友好解决方案。此外,Guava为必须使用null的情况提供了许多便利。
具体的示例
如果您要在Set中使用空值或在Map中将其用作键,请不要使用;如果在查找操作期间显式使用特殊情况下的null,则会更清楚(不足为奇)。
如果在Map中使用null作为值,请不要存储该记录;
保留单独的一组非空值的键放入一个Set(或空键)。将Map包含键的项(值为null)的情况与Map没有键的项的情况混合起来很容易。最好将这些键分开,并考虑与键关联的值为null时对您的应用程序意味着什么。
如果您在列表中使用空值-如果列表稀疏,您是否更愿意使用Map <Integer,E>?这实际上可能更有效,并且可能实际上可以更准确地满足您的应用程序需求。
考虑是否存在可以使用的自然“空对象”。并非总是如此。但是有时。例如,如果它是一个枚举,请添加一个常量以表示您期望null表示的含义。例如,java.math.RoundingMode具有UNNECESSARY值,以指示“不进行舍入,如果需要舍入则抛出异常”。
如果您确实需要null值,并且在使用null敌对的collection实现时遇到问题,请使用其他实现。例如,使用Collections.unmodifiableList(Lists.newArrayList())而不是ImmutableList。
Optional
程序员使用null的许多情况是表示某种缺席情况:也许在有值,无值或找不到值的地方。 例如,当找不到键值时,Map.get返回null。
Optional 是用非空值替换可空T引用的一种方法。 Optional可以包含非空T引用(在这种情况下,我们称该引用为“存在”),也可以不包含任何内容(在这种情况下,我们称该引用为“不存在”)。 从来没有说过“包含null”。
Optional <Integer> possible = Optional.of(5);
possible.isPresent(); //返回true
possible.get(); //返回5
尽管Optional可能具有某些相似之处,但它并不旨在直接与其他编程环境中的任何现有“ option”或“也许”构造类似。
我们在此处列出了一些最常见的Optional操作。
创建Optional
这些都是Optional上的静态方法。
Method | Description |
---|---|
Optional.of(T) | Make an Optional containing the given non-null value, or fail fast on null. |
Optional.absent() | Return an absent Optional of some type. |
Optional.fromNullable(T) | Turn the given possibly-null reference into an Optional, treating non-null as present and null as absent. |
查询方法
这些都是基于特定Optional 值的非静态方法。
Method | Description |
---|---|
boolean isPresent() | Returns true if this Optional contains a non-null instance. |
T get() | Returns the contained T instance, which must be present; otherwise, throws an IllegalStateException. |
T or(T) | Returns the present value in this Optional, or if there is none, returns the specified default. |
T orNull() | Returns the present value in this Optional, or if there is none, returns null. The inverse operation of fromNullable. |
Set asSet() | Returns an immutable singleton Set containing the instance in this Optional, if there is one, or otherwise an empty immutable set. |
Optional提供了除这些方法之外的其他一些方便的实用方法。 有关详细信息,请查阅Javadoc。
重点是什么?
除了为null命名而提高了可读性外,Optional的最大优点是其防止犯低级错误。 如果您要完全编译程序,它会迫使您积极考虑不存在的情况,因为您必须主动展开Optional并解决该情况。 Null使得简单地忘记事情变得异常容易,尽管FindBugs有所帮助,但我们认为它几乎不能解决问题。
便捷的方法
每当您希望将空值替换为某些默认值时,请使用MoreObjects.firstNonNull(T,T)。 就像方法名称所暗示的那样,如果两个输入都为null,则它会由于NullPointerException而快速失败。 如果您使用的是Optional,则有更好的选择-例如 first.or(second)
字符串中提供了一些处理可能为空的字符串值的方法。 具体来说,我们提供恰当的名称:
emptyToNull(String)
isNullOrEmpty(String)
nullToEmpty(String)
我们想强调的是,这些方法主要用于与使null strings和empty strings相等的令人讨厌的API进行交互。 每次您编写将null strings和empty strings放在一起的代码时,Guava团队都会哭泣。 (如果null strings和empty strings在含义上是不同的情况还比较好,但是将它们视为同一件事是一种令人不安的常见代码味道。)
参考
- UsingAndAvoidingNullExplained
https://github.com/google/guava/wiki/UsingAndAvoidingNullExplained