我想要一个等效于Java Optional的类,但是
非工作代码:
class MutableOptional<T> {
private var value: T? = null
private var isSet: Boolean = false
fun set(value: T)
{
this.value = value
isSet = true
}
fun unset()
{
isSet = false
value = null
}
fun get(): T
{
if (!isSet) {
throw Error("Value not set")
}
return value!! // <<< NPE here
}
}
fun f()
{
val opt = MutableOptional<Int?>()
opt.set(null)
assertNull(opt.get())
}
Run Code Online (Sandbox Code Playgroud)
问题是,如果我尝试设置null,则get()调用将失败,并出现null指针异常(由!!运算符引起)。
一些无效的建议:
注意:这个例子是综合的,我并不需要可变的可选,这只是一个简单易懂的例子,说明了我偶尔遇到的Kotlin泛型和null安全性问题。为该特定示例找到解决方案将有助于解决许多类似的问题。实际上,我为此类的不可变版本提供了一种解决方案,但它涉及为当前值和非当前值制作接口和两个实现类。这种不可变的可选变量可以用作“值”成员的类型,但我认为这只是为了克服语言限制,这是相当大的开销(还要为每个set()负责包装对象的创建)。
编译器希望您编写对所有可能T
为null的和非null的类型都是安全的代码(除非您为type参数指定not null的上限,例如T : Any
,但这不是您所需要的) 。
如果存储T?
在属性中,则它是T
与非null类型参数不同的类型,因此不允许使用T
和T?
互换使用。
但是,进行未经检查的强制转换可让您绕过限制,并将T?
值返回为T
。与非null断言(!!
)不同,在运行时不检查强制类型转换,并且在遇到时它不会失败null
。
get()
如下更改功能:
fun get(): T {
if (!isSet) {
throw Error("Value not set")
}
@Suppress("unchecked_cast")
return value as T
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
291 次 |
最近记录: |