Guava学习之Basic Utilities ——Optional安全的使用或避免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所代表的含义其实并不是很准确。例如在Map.get(key)中,返回的null可能是因为Map中存储的就是null,也可能是Map中不存在key所对应的Value。null关键字可以代表失败,成功以及任何含义。如果能使用其他的东西来代替null,那么你想表达的意思就会更明确。

有人说,正确的使用null的优势很明显。就内存速度而言使用null会很快,而且其在数组中是不可避免的。但是在应用程序代码中null会混淆逻辑,造成奇怪的bug,并且可读性很差,例如上面列举的Map.get(key)的例子。最关键的是,NULL没有指明空值意味着什么。

因此,Guava的许多工具被设计成在接收到null之后快速失败,而不是允许使用它。并且Guava提供了一定数量的设施去帮助你在必须使用null的情形下正确的使用或者避免使用。

 

实例

Set或者Map的key不要使用null。

查找操作期间显式的特殊情况为空时别使用null。

当一个Map需要使用null作为一个value,不如用独立的Set来维护非null键值(或null键)。因为这很容易混淆Map中key值对应的value为null和Map中没有对应的key,好好想想key为null对应用程序的意义,这样才是正确的做法。

在List中保存null时,会造成List变得很稀疏。这时使用 Map<Integer, E>会更有效率,更能匹配应用的需求。

考虑到存在一个为null的object能够被使用,但只是偶尔使用一次。例如:enum中可以添加一个常量表示null,再比如java.math.RoundingMode中有一个UNNECESSARY的值用来代表“不舍入,如果需要舍入,则抛出异常”。

最后,在你真的需要为null的value时,可以选择实现对null值不敏感的集合。例如:使用Collections.unmodifiableList(Lists.newArrayList()) 来代替ImmutableList。也就是说别用guava了。

 

Optional

大多数情况下使用null是为了表示某种空缺,期望有值的地方确没有,或者不能被发现。例如,Map.get 方法当找不到对应的key时会返回null。

Optional<T> 是一种替换可为空的T引用里有非空值的办法。一个Optional应该包含一个非空的T引用(由于某些原因我们称这个引用为“现在”),或者什么都没有(我们称这个情况的引用为“缺省”)。永远不会以null代表引用的状态。

Optional<Integer> possible = Optional.of(5); possible.isPresent(); // returns true possible.get(); // returns 5

Optional 并不是直接从任何其他编程环境中的任何现有的“选项”或“可能”构造的直接模拟,尽管它可能有一些相似之处。

下面列举了最普通的Optional 操作

 

Making an Optional

这些都是Optional的静态方法。

 

MethodDescription
Optional.of(T)将一个非空的值传入Optional,遇到null值时快速失败。
Optional.absent()对某些类型返回一个缺省的Optional 。
Optional.fromNullable(T)将一个可能为空的引用传入Optional,对原本不为空的不做处理,将为空的情况处理为缺省。

Query methods

这些都是对Optional<T>值特殊处理的非静态方法。

MethodDescription
boolean isPresent()instance.如果Optional包含着非null的实例则返回true。
T get()返回的T实例必须是当前的否则抛出IllegalStateException异常。
T or(T)返回Optional当前的值,如果什么都没有则返回规定的默认值。
T orNull()返回Optional当前的值,如果什么都没有则返回null,这将Optional反转为可为null的。
Set<T> asSet()返回一个不可变的单一Set包含当前Optional的实例,如果是空的则返回一个空的不可变Set。

Optional提供一系列更加实用的工具方法,详情请参阅Javadoc。

 

What's the point?

除了增加可读性之外,Optional 的最大优点是它的白痴证明性。它强迫您积极地思考缺省情况,如果您希望程序能通过编译,必须主动打开Optional 和地址的情况。NULL让人们很容易忘记事情,尽管Funbugs的帮助,但我们认为它并没有解决这个问题。

当你调用函数返回一个值的时候,会很容易忘记other.method(a, b)会返回一个null值。返回Optional 使得调用方无法忘记该情况,因为它们必须打开对象本身来编译它们的代码。

Convenience methods

不论什么时候你想用一个mull值将默认值代替,请使用MoreObjects.firstNonNull(T, T). 通过名字可以看出,如果两个输入都是null,将抛出NullPointerException. 使用Optional是一个更好的选择 -- e.g. first.or(second).

在Strings里有着处理一个为null的字符串的方法,我们为其起了恰能释义的名字。

特别强调一下,这些方法主要用于与不一致的API相连接,这些API等同于空字符串和空字符串。每次编写合并空字符串和空字符串的代码时,Guava 团队就会哭泣。(如果空字符串和空字符串意味着不同的事情,那就更好了,但是把它们当作同一件事是一种令人不安的)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值