确定修饰的类型是否可为空

Ten*_*r04 3 kotlin

假设我有一个需要一个类类型和布尔值的委托类。如果此委托所使用的属性的类型为可为空,则我具有特定的功能。为了简单起见,假设根据Boolean参数,它会为null引发错误。

class Sample<T: Any> (val type: KClass<T>,
                      val allowNulls: Boolean){
    private var value: T?

    operator fun getValue(thisRef: Any, property: KProperty<*>): T? {
        return if (allowNulls)
            value
        else
            value?: throw Exception("Value is null!")
    }

    operator fun setValue(thisRef: Any, property: KProperty<*>, value: T?) {
        this.value = value
    }
}
Run Code Online (Sandbox Code Playgroud)

我想创建一个简化函数,以轻松生成此类的实例,该实例自动确定类型是否应为可为空。同样,这对于对于可为空的属性表现不同的委托很有用。例如,这将用于允许不同的行为,具体取决于委派的属性是否可为空:

val nullableString by sample<String?>()
val nonnullString by sample<String>()
val nullableString2: String? by sample()
val nonnullString2: String by sample()
Run Code Online (Sandbox Code Playgroud)

我如何确定该类型化是否可为空?我看不到访问此信息的方法:

inline fun <reified T: Any> sample(): Sample<T>{
    return Sample(T::class, /** T is nullable */)
}
Run Code Online (Sandbox Code Playgroud)

Ily*_*lya 6

如果T是经过修饰的泛型类型参数,则可以通过简单的方法(尽管乍一看并不明显)来查找它是否可为空:

if (null is T) { 
   // T is nullable
}
Run Code Online (Sandbox Code Playgroud)

但是在您的示例中T具有Any上限,因此表达式将始终为false。


gid*_*dds 5

有一个非常简单的答案!但首先:

请记住,Kotlin中的顶级类型是Any?(可为空)。不可为空的Any是一个子类型,所有不可为空的类型都从该子类型派生。因此,如果类型不是的子类型,则该类型可以为空Any

因此,您的泛型<reified T: Any>已经限制为不可为null的类型,并且您的函数只能使用false

但是,如果您放宽该限制,则测试将变得公正null is T—毕竟,如果类型包含null为值,则该类型可以为空:

inline fun <reified T: Any?> sample(): Sample<T> {
    return Sample(T::class, null is T)
}
Run Code Online (Sandbox Code Playgroud)