我知道处理null
原语的最佳做法是使用盒装包装器,例如Integer
而不是int
,如此处所述
然而,今天使用Java 8仍然如此
引入了OptionalInt
等可选原语,其OptionalInt.empty()
有效地表示null
值?我的理解是Optionals只应该用于方法返回类型,而不能用作属性本身的类型。应该" nullable"原语仍然存储为盒装属性?它们应该只是方法返回类型中的Optional
吗?或者将OptionalInt
存储在属性本身中?
答案 0 :(得分:6)
假设你有一个方法
public void logRequest(Integer userID, String content){
//log content locally or in db or a rest call
}
假设您从特定用户的数据库中获取userID
。可以有以下几种可能性:
所以现在如果没有找到id,你会传递给logRequest
什么?
null
吗?如果该方法没有适当的空检查怎么办?它应该推断null
到底是什么? 0
还是-1
?如果null
表示0
,那么它可能与ID为0
的实际用户相矛盾。你如何区分null和0?当然,上述问题可以通过适当的文档和修复规则来解决,但它会带来更高的维护并且容易出错。正确编写的代码应该是它自己的文档。
现在说方法被声明为:
public void logRequest(OptionalInt userID, String content)
该方法本身非常清楚它需要一个可选的参数。因此只有2种情况需要处理:发送适当的参数(这意味着不使用0
绕过)。如果optional是空的,那么method正确地知道如何处理。 (与我们必须阅读其文档以预测行为之前不同。)
因此,它自己的方法声明清楚地说明了行为,而不是文档为你做的,并依赖于文档和疯狂猜测。在这种情况下,可选项非常有用。
PS:我总是觉得将null
传递给期望Integer
的方法。这绝对是错的!天哪,在爪哇,潜意识的头脑总是将整体视为原始人。它们并不意味着被置之不理。
答案 1 :(得分:3)
在您所链接的问题的答案中,解释了原始值不能为null
的原因。没有丝毫暗示使用盒装值来表示null
是“最佳实践”,事实上,没有人说使用null
是一个很好的做法。
不要试图模仿原始类型的null
值,而应该退后一步,考虑一下你要表达的内容。可以使用各种选项表达语义,使用null
不一定是最好的选择之一。表达未初始化或“已清除”值的一种简单方法是使用额外的boolean fooPropertyInitialized
变量。它比使用null
更清晰,它的开销不一定比原始值的装箱大。
这也适用于API。不要将Optional
用于财产。如果您想支持此类操作,请提供clearFooProperty()
方法,加上isFooPropertyInitialized()
。如果调用者未能首先检查getFooProperty()
状态,则initialized
抛出异常会更清晰。
请注意,也可以简单地使用对特定上下文有效的范围之外的值来表示特殊条件。这是常见的做法,例如InputStream.read()
方法返回-1
以表示到达终点。
Optional
是操作的理想返回类型,而结果没有存储空间,因此您无法将存在和值的查询拆分为两个方法调用和现值的取值范围不受限制。
但如上所述,在不知道您想要表达什么样的语义的情况下,我们无法提出建议,如果没有“最佳实践”,可能会有多种可能的解决方案......