在 Kotlin 中,有时我必须使用双重可空性。例如,当我想使用T?
whereT
可能是可空类型时,我需要双重可空性。有几种方法可以做到这一点:
Holder<T>?
Holder
在哪里data class Holder<out T>(val element: T)
-示例1boolean
标志变量 -示例1containsKey
例如Map<K, T?>
-示例1UNINITIALIZED_VALUE
代表第二种的特殊null
-示例1
最后一种方法性能最好,但也最容易出错。所以我决定将它封装在inline class Optional<T>
:
inline class Optional<out T> @Deprecated(
message = "Not type-safe, use factory method",
replaceWith = ReplaceWith("Optional.of(_value)")
) constructor(private val _value: Any?) {
val value: T?
get() =
@Suppress("UNCHECKED_CAST")
if (isPresent) _value as T
else null
val isPresent: Boolean
get() = _value != NULL
companion object {
@Suppress("DEPRECATION")
fun <T> of(value: T) = Optional<T>(value)
fun <T : Any> ofNullable(value: T?): Optional<T> =
if (value == null) EMPTY
else of(value)
@Suppress("DEPRECATION")
val EMPTY = Optional<Nothing>(NULL)
}
private object NULL
}
inline fun <T> Optional<T>.ifPresent(code: (T) -> Unit) {
@Suppress("UNCHECKED_CAST")
if (isPresent) return code(value as T)
}
inline fun <T> Optional<T>.or(code: () -> T): T {
ifPresent { return it }
return code()
}
第一个问题Optional
是public constructor
,它允许使用不匹配类型的参数创建实例。
第二个问题是在测试时注意到的。这是失败的测试:
emptyOr { Optional.EMPTY }.value assertEql null
fun <T> emptyOr(other: () -> T): T = Optional.EMPTY.or(other)
例外:
Exception ClassCastException: Optional$NULL cannot be cast to Optional
at (Optional.kt:42) // emptyOr { Optional.EMPTY }.value assertEql null
如果我从中删除inline
修饰符Optional
,则测试将通过。
问:有什么方法可以在不删除inline
修饰符的情况下解决这些问题Optional
?
1示例包括一些上下文。请在写下我添加了错误链接之前完整阅读它们。