Kotlin - 不能使用'T'作为具体类型参数.请改用一个班级

Kru*_*hah 7 java generics android sharedpreferences kotlin

我有一个简单的帮助函数来从SharedPreferences获取值,如下所示:

operator inline fun <reified T : Any> SharedPreferences.get(key: String, defaultValue: T? = null): T? {
    return when (T::class) {
        String::class -> getString(key, defaultValue as? String) as T?
        Int::class -> getInt(key, defaultValue as? Int ?: -1) as T?
        Boolean::class -> getBoolean(key, defaultValue as? Boolean ?: false) as T?
        Float::class -> getFloat(key, defaultValue as? Float ?: -1f) as T?
        Long::class -> getLong(key, defaultValue as? Long ?: -1) as T?
        else -> throw UnsupportedOperationException("Not yet implemented")
    }
}
Run Code Online (Sandbox Code Playgroud)

我已经使用了reified类型参数来切换类类型,因为它是一个操作符函数,我应该能够使用如下方括号语法调用:

val name: String? = prefs[Constants.PREF_NAME]
Run Code Online (Sandbox Code Playgroud)

但是,每次调用它时,都会抛出UnsupportedOperationException,指示函数无法获取类类型.

当我附加调试器并进行评估时T::class,它给了我一个错误"Cannot use 'T' as reified type parameter. Use a class instead."

我的功能出了什么问题?我无法抓住这个错误.有人可以帮忙吗?

编辑:全班都在这里,这是我得到错误的地方.

更新:似乎是Kotlin编译器问题.跟踪https://youtrack.jetbrains.com/issue/KT-17748https://youtrack.jetbrains.com/issue/KT-17748以获取更新.

Jor*_*nee 5

问题很奇怪,但似乎与(无论如何都是非法表达)Int::class不同。Int?::class

当您添加以下行时:

println(T::class)
Run Code Online (Sandbox Code Playgroud)

对于该get方法,并调用val age: Int? = prefs["AGE", 23],您将看到它打印java.lang.Integer

好像Int?是翻译成的java.lang.Integer

一个可能的(但恕我直言有点hacky)解决方案是使用对Java类的引用作为以下情况的情况:

operator inline fun <reified T : Any> get(key: String, defaultValue: T? = null): T? {
    return when (T::class) {
        String::class -> getString(key, defaultValue as? String) as T?
        java.lang.Integer::class -> getInt(key, defaultValue as? Int ?: -1) as T?
        java.lang.Boolean::class -> getBoolean(key, defaultValue as? Boolean ?: false) as T?
        java.lang.Float::class -> getFloat(key, defaultValue as? Float ?: -1f) as T?
        java.lang.Long::class -> getLong(key, defaultValue as? Long ?: -1) as T?
        else -> throw UnsupportedOperationException("Not yet implemented")
    }
}
Run Code Online (Sandbox Code Playgroud)