Nullable and NonNull Type Cast

Why the compiler allows the cast between a nullable and non-null?

fun test(text: CharSequence?): String {
    return (text as String)
}

this code compiles, and once you send a non-null text it works, but as it allows nullables, the following happens when you send null:

kotlin.TypeCastException: null cannot be cast to non-null type kotlin.String

P.S. I know cast is a dangerous operation, but once kotlin proposes the null-safety I don’t see why do not check to casts, so it is the motivation of my question.

Because a typecast is by itself already an unsafe operation. A typecast (especially in Kotlin with autocasts) is basically saying to the compiler that you know more than it does. The compiler says fine, but if it breaks it’s on you (you get to keep the pieces).

In other words text could just as well be a StringBuilder as null.

2 Likes

Thank you for your answer Paul.

I’m wondering if it is a good idea to the compiler check at least the null possibility. So, given that sample, the compiler will force me to do something like text as String? or text ?: "" as String.

I’m mean, it is still unsafe and will break when you send a StringBuilder, but it will be a typecast exception not related to null non-null types.

The type cast of swift is safer and more robust. Swift provide ‘as!’, ‘as’ and ‘as?’, If using ‘as’ on a nullable variable, the compiler will complain. I think Kotlin can do the same thing on the type cast to make the code more robust.

Kotlin has “as?” for safe nullable casting. You can always check the type before casting instead of doing unchecked casts (or use smart casting)

fun main() {
  val str1: String? = null
  val str2: String? = "Not null"

  val canCastStr1 = (str1 as? String) != null
  val canCastStr2 = (str2 as? String) != null

  println("Cast str1 to String: $canCastStr1")
  println("Cast str2 to String: $canCastStr2")
}