Java 8 原始的;空值“;和Java8

Java 8 原始的;空值“;和Java8,java-8,optional,Java 8,Optional,我知道处理null原语的最佳实践是使用装箱包装,例如Integer,而不是int,如本文所述 然而,这在今天的Java8中仍然是正确的吗 引入了可选原语,如optionant,其optionant.empty()有效地表示null值?我的理解是,Optionals应该只用于方法返回类型,而不是作为属性本身的类型。“可空”原语是否仍应存储为装箱属性?它们是否应该仅在方法返回类型中是可选的?或者在属性本身中存储为optionant?假设您有一个方法 public void logRequest(I

我知道处理
null
原语的最佳实践是使用装箱包装,例如
Integer
,而不是
int
,如本文所述

然而,这在今天的Java8中仍然是正确的吗
引入了可选原语,如
optionant
,其
optionant.empty()
有效地表示
null
值?我的理解是,Optionals应该只用于方法返回类型,而不是作为属性本身的类型。“可空”原语是否仍应存储为装箱属性?它们是否应该仅在方法返回类型中是可选的?或者在属性本身中存储为
optionant

假设您有一个方法

public void logRequest(Integer userID, String content){
    //log content locally or in db or a rest call
}
假设您从数据库中为特定用户获取
userID
。可能存在以下可能性:

  • DB返回一个用户ID
  • 找不到id
那么现在如果找不到id,您将传递什么到
logRequest

  • 是否传递
    null
    ?如果该方法没有适当的空检查怎么办。它应该推断出什么
    null
  • 您应该通过
    0
    还是
    -1
    ?如果
    null
    表示
    0
    ,则它可能与ID为
    0
    的实际用户相矛盾。如何区分null和0
当然,上面的问题可以通过适当的文档和修改规则来解决,但它会导致更高的维护,并且容易出错。正确编写的代码应该是它自己的文档

现在假设方法声明为:

public void logRequest(OptionalInt userID, String content)
该方法本身非常清楚地表明,它需要一个可选的参数。因此,只有两种情况需要处理:发送一个适当的参数(这意味着使用
0
不能绕过)。如果可选项为空,则方法正确地知道如何处理。(不像以前,我们必须阅读它的文档来预测行为)

因此,它自己的方法声明清楚地说明了行为,而不是为您编写文档并依靠文档和胡乱猜测。在这种情况下,选项非常有用


PS:我总是觉得把
null
传递给一个需要
整数的方法有点紧张。感觉绝对不对!天哪,在Java中,潜意识总是把INT当作原语。它们并不意味着为空。

在您链接的问题的答案中,解释了原语值为什么不能为
null
。没有任何迹象表明使用装箱值表示
null
是“最佳实践”,事实上,还没有人说使用
null
是一种好的实践

您不应该尝试为基本类型模拟
null
值,而应该后退一步,考虑要表达什么。这种语义可以使用多种选项来表达,使用
null
不一定是最佳选择之一。表示未初始化或“清除”值的一种简单方法是使用一个额外的
boolean fooPropertyInitialized
变量。它比使用
null
更清晰,并且它的开销不一定比基本值的装箱更大

这也适用于API。不要对属性使用
可选
。如果您想支持这样的操作,只需提供一个
clearFooProperty()
方法,外加一个
isFooPropertyInitialized()
。如果调用方未能首先检查
initialized
状态,则让
getFooProperty()
抛出异常会更干净

注意,也可以简单地使用对特定上下文有效的范围之外的值来表示特殊条件。这是常见的做法,比如
InputStream.read()
方法返回
-1
以发送到达末尾的信号

可选
是操作的理想返回类型,而结果没有存储空间,因此无法将查询存在和值拆分为两个方法调用,并且当前值的值范围不受限制


但是,如前所述,如果不知道您想要表达什么样的语义,我们就无法提出建议,而且如果没有“最佳实践”,可能会有不止一种可能的解决方案……

您知道使用
Optionant
比普通的
Integer
有什么优势吗?对于后者,您只需将其分配给
null
,并以与
optionant
isEmpty()相同的方式相应地处理它。这是一个有趣的问题。在应用程序的数据模型中,值为“null”的语义是什么?好的,那么每个人所说的语义是什么意思?比如使用0或-1来标记缺少的int值?或者使用了什么业务上下文?“好吧,那么每个人所说的语义是什么意思?”语义(“单词的含义”)是指有一个空的
整数
。空表示“空”吗?null仅在某些初始化之前有效吗?null是否表示发生了错误?等等
optionant
有一个特定的含义。这是一个非常有趣的答案。有人告诉我,将Optionals作为参数传递给方法不是最优的,应该使用重载。然而,在这样的一些情况下,将可选项作为参数传递语义是有意义的。我认为最好忘记最优性,因为这样的小事情几乎不会影响性能:)。但是,是的,我更喜欢在大多数情况下覆盖,因为它更干净。