Kotlin - Cannot use 'T' as reified type parameter. Use a class instead

Krupal Shah :

I have a simple helper function to get value from SharedPreferences like this :

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")
    }
}

I have used reified type parameter to have switching over class type and since it is an operator function, I should be able to call with the square brackets syntax like below :

val name: String? = prefs[Constants.PREF_NAME]

But, every time I call it, UnsupportedOperationException is thrown indicating function is not able to get class type.

When I attach debugger and evaluate T::class, It is giving me an error "Cannot use 'T' as reified type parameter. Use a class instead."

What's wrong with my function? I could not catch the mistake. can anyone help?

Edit : The whole class is here and this is where I get the error.

Update: It seems to be Kotlin compiler issue. Track https://youtrack.jetbrains.com/issue/KT-17748 and https://youtrack.jetbrains.com/issue/KT-17748 for updates.

Jorn Vernee :

The problem is curious, but it seems that Int::class is not the same as Int?::class (which is an illegal expression any ways).

When you add the line:

println(T::class)

To the get method, and call val age: Int? = prefs["AGE", 23], you will see that it prints java.lang.Integer.

It seems like Int? is translated into java.lang.Integer.

A possible (but imho kind of hacky) solution is to use the references to Java classes as the cases for when:

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")
    }
}

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=457684&siteId=1