ZetCode

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.

UnsafeCast.kt
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.

SafeCast.kt
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.

NumericCast.kt
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.

InheritanceCast.kt
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.

SmartCast.kt
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.

GenericCast.kt
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.

ReifiedCast.kt
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

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

My name is Jan Bodnar, and I am a passionate programmer with many years of programming experience. I have been writing programming articles since 2007. So far, I have written over 1400 articles and 8 e-books. I have over eight years of experience in teaching programming.

List all Kotlin tutorials.