Skip to main content

Introduction

Type casting is the process of converting a variable data type from one to another.

Keep in mind that type casting operation is error-prone one.
This is why you learn about casting operation. If not, fatal error or exception would occur.

Any

Any is the root of the Kotlin class, which means that every Kotlin class has Any as a parent class.
In other terms, any Kotlin variable can have Any as a type.

Unsafe casting

You can use as keyword for unsafe casting

Let me show you explicit unsafe casting using as.

val num : Any = 42
val str1 : String = num as String
println(str1)

This code would lead to following error:

Exception in thread "main" java.lang.ClassCastException: 
class java.lang.Integer cannot be cast to class java.lang.String

Similarly, the as cast operator should fail when nullable types are involved, as shown below

val num : Any? = null
val str1 : String = num as String
println(str1)

So, everytime you perform an explicit unsafe cast through the as operator
You should consider that a ClassCastException might be thrown.
If you want to prevent this error from crashing your application, you must handle it as follows:

val num : Any? = null
try {
val str1: String = num as String
println(str1)
} catch (e: ClassCastException) {
println("Cast failed!")
}

Safe Casting

The as? cast operator is called safe because it returns null when the cast can't be performed.
In other words, it's considered safe because it allows you to avoid exceptions, returning null on failure.

as? operator allow receiver variable should always be nullable when casting fails.

val champ : Any = "khazix"
val str1 : String = champ as? String
println(str1)

This code would lead to following error:

Kotlin: Type mismatch: inferred type is String? but String was expected

Because str1 doesn't have a nullable type. \ To make it work, all you have to do it declare str1 as String?:

val champ : Any = "khazix"
val str1 : String? = champ as? String
println(str1)

Avoid ClassCastException with as? keyword

var num: Any = 42
val str1: String? = num as? String
println(str1)

This would no longer fail. it would print:

null

You can avoid ClassCastException even though fail since 'Integer' can't be cast to 'String'.
So the try ~ catch statement is no longer required when using as? the safe cast operator.

You have to consider receiver variable has null value when cast failed.

val str1: String? = num as? String

if (str1 == null) {
// Cast failed!
} else {
// Cast succeeded!
}

📝 Summary

  • Use as operator only when you can make sure the cast will be successful.
    For example when casting a type to its supertype in an inheritance hierarchy.

  • Use as? operator with handling null-checking code. Your application wouldn't be shut down even type casting fails.
    However, required how to deal with them.

🔗 Reference