Question
How to Check Type at Runtime in Kotlin: instanceof, is, and Smart Casts
Question
In Kotlin, I have a method that accepts a parameter typed as a general object, and I may pass instances of different classes when calling it.
In Java, I can use instanceof to check what class an object belongs to at runtime.
How can I do the same kind of runtime type check in Kotlin? What is the Kotlin equivalent of instanceof?
Short Answer
By the end of this page, you will understand how Kotlin checks an object's type at runtime using is and !is, how smart casts work after a successful type check, and when to use when for handling multiple possible types. You will also see common mistakes, practical examples, and how this pattern is used in real Kotlin code.
Concept
Kotlin does not use the Java keyword instanceof. Instead, Kotlin uses the is operator for runtime type checks.
For example:
if (value is String) {
println("This is a String")
}
This checks whether value is an instance of String at runtime.
Kotlin also provides !is, which means “is not of this type”:
if (value !is String) {
println("This is not a String")
}
Why this matters
In real programs, you often receive values whose exact type is not known in advance:
- function parameters typed as
Any - API responses mapped into different models
- sealed class hierarchies
- event systems
- error objects
Runtime type checking lets you safely decide what to do based on the actual object type.
A key Kotlin feature: smart casts
One major improvement over Java is that after checking with is, Kotlin can automatically treat the variable as that type inside the safe branch. This is called a smart cast.
{
(value String) {
println(value.length)
}
}
Mental Model
Think of is as checking a label on a package before opening it.
Anymeans “this is some package, but we do not yet know what is inside.”is Stringmeans “check whether the package is labeled String.”- If the label matches, Kotlin lets you open it as that type automatically.
So instead of saying, “I know this is probably a String, let me cast it,” Kotlin says, “First verify the label, then I will safely treat it as a String for you.”
That automatic trust after the check is the smart cast.
Syntax and Examples
Basic syntax
if (value is String) {
println("value is a String")
}
if (value !is String) {
println("value is not a String")
}
Example with Any
fun describe(value: Any) {
if (value is Int) {
println("Integer: $value")
} else if (value is String) {
println("String with length ${value.length}")
} else {
println("Unknown type")
}
}
Explanation
valueis declared asAny, so it can hold values of many types.value is Intchecks whether the runtime object is anInt.value is Stringchecks whether it is a .
Step by Step Execution
Consider this example:
fun printInfo(value: Any) {
if (value is String) {
println("Text: ${value.uppercase()}")
} else {
println("Not a string")
}
}
fun main() {
printInfo("kotlin")
printInfo(42)
}
Step by step
First call: printInfo("kotlin")
- The argument is the string
"kotlin". - Inside
printInfo,valuehas declared typeAny. - Kotlin evaluates
value is String. - The check is
true. - Kotlin smart casts
valuetoStringinside theifblock. value.uppercase()runs and produces .
Real World Use Cases
1. Handling mixed input values
A function may receive values from different sources:
fun logValue(value: Any) {
when (value) {
is String -> println("Message: $value")
is Int -> println("Count: $value")
is Boolean -> println("Enabled: $value")
}
}
2. Working with API or parsing results
After parsing data, the result may be one of several model types:
when (result) {
is Success -> println(result.data)
is Error -> println(result.message)
}
3. UI event handling
Applications often process different event objects:
when (event) {
is ClickEvent -> handleClick(event)
is ScrollEvent -> handleScroll(event)
}
4. Error handling
You may inspect exception types:
Real Codebase Usage
In real Kotlin projects, developers often use type checks in a few common patterns.
Guard clauses
Exit early if a value is not the expected type:
fun process(value: Any) {
if (value !is String) return
println(value.length)
}
This keeps the rest of the function clean.
when for branching by type
fun render(item: Any) {
when (item) {
is String -> println(item)
is Int -> println(item * 2)
else -> println("Unsupported")
}
}
Validation before using data
fun save(input: Any) {
require(input is String) { "Input must be a String" }
println(input.length)
}
Working with interfaces and polymorphism
Common Mistakes
1. Using instanceof in Kotlin
This is Java syntax, not Kotlin syntax.
Wrong
if (value instanceof String) {
println(value)
}
Correct
if (value is String) {
println(value)
}
2. Using Object instead of Any
In Kotlin, the usual root type is Any, not Java's Object.
Better
fun process(value: Any) {
println(value)
}
3. Forgetting about nullability
Any cannot hold null. Use Any? if null is possible.
{
(value String) {
println(value.length)
}
}
Comparisons
is vs Java instanceof
| Feature | Kotlin | Java |
|---|---|---|
| Type check operator | is | instanceof |
| Negative check | !is | !(x instanceof Type) |
| Automatic cast after check | Yes, smart cast | No, usually manual cast needed |
is vs as
| Operator | Purpose | Safe? | Result |
|---|
Cheat Sheet
Runtime type checking in Kotlin
if (value is String) { }
if (value !is String) { }
Smart cast
if (value is String) {
println(value.length)
}
After a successful is check, Kotlin often smart casts the value.
Multiple types with when
when (value) {
is String -> println(value.length)
is Int -> println(value)
else -> println("Unknown")
}
Safe cast
val text = value as? String
println(text?.length)
Force cast
val text = value as String
Use carefully: this throws an exception if the type is wrong.
Root object types
FAQ
What is the Kotlin equivalent of instanceof?
Use the is operator.
if (value is String) {
println("It is a String")
}
How do I check that an object is not a type in Kotlin?
Use !is.
if (value !is String) {
println("It is not a String")
}
What type should I use instead of Java Object in Kotlin?
Use Any for non-null values and Any? if null is allowed.
Does is also match subclasses?
Yes. If an object is an instance of a subclass, is returns true for the parent type or implemented interface.
Do I need to cast after using is?
Usually no. Kotlin often smart casts automatically inside the checked branch.
What is the difference between and in Kotlin?
Mini Project
Description
Create a small Kotlin function that receives values of different runtime types and prints a useful message for each one. This demonstrates how to use is, when, and smart casts in a practical way, similar to handling mixed API results, events, or user input.
Goal
Build a type inspector that accepts a value of type Any? and handles null, strings, integers, and booleans safely.
Requirements
Requirement 1 Requirement 2 Requirement 3
Keep learning
Related questions
Accessing Kotlin Extension Functions from Java
Learn how Kotlin extension functions are compiled and how to call them correctly from Java with clear examples and common pitfalls.
Android AlarmManager Example: Scheduling Tasks with AlarmManager
Learn how to use Android AlarmManager to schedule tasks, set alarms, and handle broadcasts with a simple beginner example.
Android Foreground Service Notification Channels in Kotlin
Learn why startForeground fails on Android 8.1 and how to create a valid notification channel for foreground services in Kotlin.