我的第一个建议是,尽量避免使用Optional
种考特林语言.可为空的类型提供了相同的编译时保证,即一个值是否可以容纳空值,它们迫使您在正确的位置判断是否为空,而且它们更加惯用(还有大量的语法糖分可以帮助处理可为空的值,如?:
或?.
操作符).
现在回到你的具体问题上,你看到的是几个因素对你不利的组合:
在函数签名中,根本没有约束T
.这意味着T
可以是一个可空的类型(例如,String?
),这反过来又意味着这个函数接受空值.注意,Optional.of
是一个Java函数,它期望一个非空值,如果给出null
作为参数,则抛出NPE.在这种情况下,您可能需要仔细判断抛出NPE是否是您想要的函数.
另一个(更大的)问题是,您可能会假设Optional<T>
在T
中是协变的,但它实际上是不变的(可能是因为它是一个Java类,没有对它做任何特殊的处理,但确实有an issue to change this个).更清楚地说,这意味着即使A
是B
的子类型,Optional<A>
也不是Optional<B>
的子类型,因此不能将Optional<String>
值赋给类型为Optional<String?>
的变量.
第三件事是,像of
和ofNullable
这样的Optional
个工厂函数实际上返回您传递的类型的不可为空的投影,因此总是Optional<T & Any>
(因为空值将分别失败或导致空的Optional
).例如,Optional.of<String?>("abc")
仍然返回Optional<String>
,这与Optional
在T
中是不变的事实不符.
这解释了为什么您的optional
变量的显式类型(Optional<T>
)是不正确的.因为Optional.of
返回Optional<T & Any>
,不能将其赋给Optional<T>
类型的变量(即使T & Any
是T
的子类型).
这可能有很多行话,所以让我使用您的字符串示例来澄清一下,但是我们不使用String
作为T
,而是使用String?
:
fun returnOptionalOfString(t: String?): Optional<String?> {
val optional: Optional<String?> = Optional.of(t) // error here
return optional
}
在这里,您将看到赋值的相同错误,但用更简单的术语.
正如@marstran已经提到的,解决所有这些问题的一种方法是在处理Optional
时只使用不可为空的类型.在您的例子中,这意味着使用: Any
约束T
:
fun <T : Any> returnOptionalOf(t: T): Optional<T> {
val optional: Optional<T> = Optional.of(t)
return optional
}