Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic cast in Kotlin

I want to cast Any to Int by using KClass<Int>, having a KClass<Int> and a Any which is actually Int.

fun <T> cast(any: Any, clazz: KClass<*>): T = clazz.java.cast(any) 

cast(0, Int::class)

However, I got this error.

java.lang.ClassCastException: Cannot cast java.lang.Integer to int

Do you know any solution except any as Int?

like image 435
mmorihiro Avatar asked Dec 19 '16 09:12

mmorihiro


People also ask

What is dynamic Kotlin?

dynamic is a special type in Kotlin/JS. It basically turns off Kotlin's type checker. That is needed in order to interoperate with untyped or loosely typed environments, such as the JavaScript ecosystem.

Is Kotlin dynamic type?

Dynamic type Being a statically typed language, Kotlin still has to interoperate with untyped or loosely typed environments, such as the JavaScript ecosystem. To facilitate these use cases, the dynamic type is available in the language: val dyn: dynamic = ...

What is cast in Kotlin?

Type check is a way of checking the type( DataType ) or Class of a particular instance or variable while runtime to separate the flow for different objects. In few languages, it's also denoted as Run Time Type Identification (RTTI) .

Is Kotlin a dynamic language?

Kotlin is a statically typed language, which makes it different from the dynamically typed JavaScript.

What is the dynamic type in Kotlin?

The dynamic type basically turns off Kotlin's type checker: A value of the dynamic type can be assigned to any variable or passed anywhere as a parameter. Any value can be assigned to a variable of the dynamic type or passed to a function that takes dynamic as a parameter.

What is type casting in Kotlin with examples?

Kotlin Type Casting with examples. Type casting is a process of converting one data type to another type, for example – converting int to long, long to double etc. In this tutorial we will learn how to do type conversion in Kotlin.

Why are the class parameters any and any in Kotlin?

Because the type of the parameter any is Any, it's always a reference type and primitives will be boxed. For the second parameter, it seems that Kotlin reflection will prefer primitive types to reference types, which is why Int::class.java will default to ìnt, not Integer.

What is an unsafe cast in Kotlin?

And so, it's called unsafe. The unsafe cast in Kotlin is done by the infix operator as. Note that null cannot be cast to String, as this type is not nullable. If y is null, the code above throws an exception. To make code like this correct for null values, use the nullable type on the right-hand side of the cast:


2 Answers

Try to change your code to

fun <T: Any> cast(any: Any, clazz: KClass<out T>): T = clazz.javaObjectType.cast(any) 

Explanation

Because the type of the parameter any is Any, it's always a reference type and primitives will be boxed. For the second parameter, it seems that Kotlin reflection will prefer primitive types to reference types, which is why Int::class.java will default to ìnt, not Integer. By using javaObjectType we force the usage of the boxed reference type.

Alternative

You could also use the following function definition:

inline fun <reified T: Any> cast(any: Any): T = T::class.javaObjectType.cast(any) 

// usage

cast<Int>(0)
like image 111
Kirill Rakhman Avatar answered Sep 21 '22 00:09

Kirill Rakhman


Kirill Rakhman 's answer works well for non-nullable type. But we cannot have T::class if T is nullable. So I suggest the following to deal with nullable type.

inline fun <reified T> cast(any: Any?): T = any as T

Usage

val l32: Number = cast(32L)
val ln1: Number? = cast(null) // works
val ln2: Number = cast(null) // fails at runtime
like image 27
mcoolive Avatar answered Sep 17 '22 00:09

mcoolive