Kotlin as Keyword
last modified April 19, 2025
Kotlin's type casting system provides safe and unsafe ways to convert between
types. The as
keyword is central to type casting operations. This
tutorial explores the as
keyword in depth with practical examples.
Basic Definitions
The as
keyword in Kotlin is used for type casting. It comes in two
forms: unsafe cast (as
) and safe cast (as?
). The unsafe
cast throws an exception if the conversion fails, while the safe cast returns
null.
Unsafe Cast with as
The basic as
operator performs an unsafe cast. If the cast fails, it
throws a ClassCastException
. Use this when you're certain about the
type.
package com.zetcode fun main() { val obj: Any = "Hello Kotlin" val str: String = obj as String println(str.length) // Output: 12 }
Here we cast an Any
type to String
using as
.
The cast succeeds because the underlying object is a String. The code then prints
the string's length.
Safe Cast with as?
The safe cast operator as?
returns null instead of throwing an
exception when the cast fails. This is safer for cases where type is uncertain.
package com.zetcode fun main() { val obj: Any = 123 val str: String? = obj as? String println(str) // Output: null }
Here we attempt to cast an Int to String using as?
. Since this cast
is impossible, the result is null instead of an exception. This is useful when
processing unknown data types.
Casting Between Numeric Types
Kotlin requires explicit casting between numeric types. The as
keyword can be used for this purpose, but only when the types are compatible.
package com.zetcode fun main() { val x: Int = 100 val y: Long = x.toLong() // Preferred way val z: Long = x as Long // Compile error println(y) }
This example shows that direct casting between numeric types with as
isn't allowed. Instead, use the conversion functions like toLong
.
The commented line would cause a compilation error.
Casting in Inheritance Hierarchy
The as
keyword works well when casting within an inheritance
hierarchy. You can cast a parent class to a child class if the object is
actually of the child type.
package com.zetcode open class Animal class Dog : Animal() { fun bark() = println("Woof!") } fun main() { val animal: Animal = Dog() val dog: Dog = animal as Dog dog.bark() // Output: Woof! }
Here we successfully cast an Animal to Dog because the underlying object is actually a Dog. After the cast, we can call Dog-specific methods like bark().
Smart Casts
Kotlin's smart casts automatically handle casting after type checks. While not
using as
directly, they're related to type casting concepts.
package com.zetcode fun printLength(obj: Any) { if (obj is String) { println(obj.length) // Smart cast to String } } fun main() { printLength("Kotlin") // Output: 6 printLength(123) // No output }
After checking obj is String
, Kotlin automatically casts obj to
String within the if block. This eliminates the need for explicit as
casting in many cases.
Generics and Casting
With generics, you might need to cast to generic types. The as
keyword can be used here, but be cautious about type safety.
package com.zetcode fun <T> castToType(obj: Any): T? { return obj as? T } fun main() { val result: String? = castToType("Hello") println(result) // Output: Hello val failed: Int? = castToType("Not a number") println(failed) // Output: null }
This generic function attempts to cast any object to type T using safe cast. The first call succeeds while the second fails gracefully, returning null instead of throwing an exception.
Reified Type Parameters
With reified type parameters in inline functions, you can access the actual type at runtime and perform safer casts.
package com.zetcode inline fun <reified T> safeCast(obj: Any): T? { return obj as? T } fun main() { val s: String? = safeCast("Kotlin") val i: Int? = safeCast(123) println(s) // Output: Kotlin println(i) // Output: 123 }
The reified type parameter preserves the type information at runtime, making the safe cast operation more type-safe. This is particularly useful in generic functions where you need to perform type checks.
Best Practices for Type Casting
- Prefer safe casts: Use
as?
when unsure about the type to avoid runtime exceptions. - Use smart casts: Leverage Kotlin's smart casting when possible for cleaner code.
- Avoid unsafe casts: Only use
as
when you're certain about the type. - Consider alternatives: For numeric types, use conversion functions instead of casting.
- Use reified types: For generic functions, consider using reified type parameters for safer casting.
Source
Kotlin Type Casts Documentation
This tutorial covered Kotlin's as
keyword in depth, showing both
safe and unsafe casting operations. We explored various scenarios including
inheritance, generics, and smart casts. Proper use of type casting can make your
code more flexible while maintaining type safety.
Author
List all Kotlin tutorials.