In Kotlin, you can perform type checks to check the type of an object at runtime. Type casts convert objects to a different type.
To learn specifically about generics type checks and casts, for example
List<T>
,Map<K,V>
, see Generics type checks and casts.
{type="tip"}
Use the is
operator or its negated form !is
to perform a runtime check that identifies whether an object conforms to a given type:
if (obj is String) {
print(obj.length)
}
if (obj !is String) { // Same as !(obj is String)
print("Not a String")
} else {
print(obj.length)
}
In most cases, you don't need to use explicit cast operators in Kotlin because the compiler tracks the
is
-checks and explicit casts for immutable values and inserts (safe) casts automatically when necessary:
fun demo(x: Any) {
if (x is String) {
print(x.length) // x is automatically cast to String
}
}
The compiler is smart enough to know that a cast is safe if a negative check leads to a return:
if (x !is String) return
print(x.length) // x is automatically cast to String
Or if it is on the right-hand side of &&
or ||
and the proper check (regular or negative) is on the left-hand side:
// x is automatically cast to String on the right-hand side of `||`
if (x !is String || x.length == 0) return
// x is automatically cast to String on the right-hand side of `&&`
if (x is String && x.length > 0) {
print(x.length) // x is automatically cast to String
}
Smart casts work for when
expressions
and while
loops as well:
when (x) {
is Int -> print(x + 1)
is String -> print(x.length + 1)
is IntArray -> print(x.sum())
}
Note that smart casts work only when the compiler can guarantee that the variable won't change between the check and its usage.
{type="warning"}
Smart casts can be used in the following conditions:
val local variables
|
Always, except local delegated properties. |
val properties
|
If the property is private , internal , or if the check is performed in the same module where the property is declared. Smart casts can't be used on open properties or properties that have custom getters.
|
var local variables
|
If the variable is not modified between the check and its usage, is not captured in a lambda that modifies it, and is not a local delegated property. |
var properties
|
Never, because the variable can be modified at any time by other code. |
Usually, the cast operator throws an exception if the cast isn't possible. Thus, it's called unsafe.
The unsafe cast in Kotlin is done by the infix operator as
.
val x: String = y as String
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:
val x: String? = y as String?
To avoid exceptions, use the safe cast operator as?
, which returns null
on failure.
val x: String? = y as? String
Note that despite the fact that the right-hand side of as?
is a non-nullable type String
, the result of the cast is nullable.