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 the usage. More specifically, smart casts can be used under the following conditions:
val
local variables - always, with the exception of local delegated properties.val
properties - if the property is private or internal or if the check is performed in the same module where the property is declared. Smart casts cannot be used on open properties or properties that have custom getters.var
local variables - if the variable is not modified between the check and the 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. And so, 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-null type String
, the result of the cast is nullable.
Please see the corresponding section in the generics documentation page for information on which type checks and casts you can perform with generics.