Skip to main content
The is operator evaluates whether an object is an instance of a specified type at runtime. It performs runtime type identification (RTTI) and returns a Boolean. Its negated counterpart, !is, returns true if the object is not an instance of the specified type.

Compiler Mechanics

Smart Casting When an is check evaluates to true, the Kotlin compiler performs data-flow analysis. If the compiler can guarantee that the variable will not be modified between the check and its subsequent usage, it automatically applies a smart cast. Within the scope where the condition holds true, the variable is treated as the target type, eliminating the need for the explicit cast operator (as).
when Expressions The is operator is natively integrated into when expressions as a branch condition. This provides an idiomatic mechanism for multi-way type checking and smart casting without requiring explicit if-else chains.
Nullability Resolution The is operator strictly adheres to Kotlin’s type system regarding nullability.
  • Checking against a non-nullable type (is Type) implicitly acts as a null check. If the operand is null, the expression evaluates to false.
  • Checking against a nullable type (is Type?) evaluates to true if the operand is null, because null is a valid instance of Type?.

JVM Type Erasure Limitations

Because Kotlin compiles to the JVM (in its primary target), generic type arguments are generally erased at runtime. Consequently, the is operator cannot evaluate parameterized types with specific type arguments by default. To perform type checks on generic collections or classes, you must use star-projected types (*), which verify the base class but not the generic payload.
Exceptions to Type Erasure There are three specific scenarios where the compiler permits the is operator to evaluate exact generic type arguments:
  1. Reified Type Parameters: When using inline functions with reified type parameters, the compiler inlines the actual type at the call site, preserving the type information at runtime.
  2. Arrays: Arrays in Kotlin are reified on the JVM. They retain their component types at runtime, allowing direct type checks against specific array types.
  3. Statically Known Type Arguments: If the compiler’s static type checking already guarantees the generic type argument based on the variable’s declaration, it permits an is check on the base class.
Tired of Poor Kotlin Skills? Fix That With Deep Grasping!Learn More