Kotlin Type Checking, Kotlin Type Casting

Filed Under: Kotlin
kotlin smart casts

Today we will look into Kotlin type checking and smart type casting. We will use Kotlin Online playground for code snippets.

Kotlin Type Checking

Type Checking is the way to check the type of a data at runtime. In Java, we have the instanceof keyword to check the type. Kotlin uses is and !is keywords to check whether a property is and is not of a certain type respectively.

Let’s look at an example code for the same.


var myProperty = "xyz"
var otherProperty = 1
if(myProperty is String)
{
    println("type is String")
}
else{
    println("unknown type")
}

if(otherProperty !is Double)
{
    println("not a string")
}
else{
    println("unknown type")
}

The first if-else expression would print type is String. The second would give a compilation error since Kotlin is powerful enough to determine the types at compile time itself.

Let’s create a list of Any objects and check the type of each element.

We’ll use the when statement to check the type of each element in a for loop.


val anyList: List<Any> = listOf("JournalDev.com", "Java", 101, 12.5f,12.5456789,false)

    for(value in anyList) {
        when (value) {
            is String -> println("String: '$value'. Capitalize :${value.capitalize()}")
            is Int -> println("Integer: '$value'")
            is Double -> println("Double: '$value'")
            is Float -> println("Float: '$value'")
            else -> println("Unknown Type")
        }
    }

Following is the output of the above code.
kotlin type checking

Kotlin Smart Type Casting

Smart type casting is one of the most interesting features available in Kotlin. It automatically casts a property to the desired type on the right hand side if the condition meets.


fun getName(obj: Any?) {
        if (obj == null || obj !is String) {
            return
        }
        val string = obj
        println("Length of the string is ${string.length}")
    }

    getName(null)
    getName("Anupam")

In the above code, we don’t need to unwrap the optional. If the smart cast passes the above null checker, optional is unwrapped automatically.

The output printed from the above piece of code is given below.
kotlin smart type casting

The same equivalent code in Java would look like this:


class MyJava
{
	public static void main (String[] args) throws java.lang.Exception
	{
		// your code goes here
 
	MyJava mj = new MyJava();
	mj.printStringLength("Anu");
 
	}
 
	public void printStringLength(Object obj) {
        if (obj instanceof String) {
        String str = (String) obj;
        System.out.print("String substring is ");
        System.out.print(str.substring(1));
 
      }
    }
}

In the above code, we’re first checking the instanceOf and then explicitly type casting. Kotlin makes it way simpler thanks to Smart Casting.

Smart Casting With Binary Operators

Smart Casting is also possible with binary operators as shown in the below code.


fun newStringOnlyIfLength6(str: Any): Boolean {
        return str is String && str.length == 6
}

print(newStringOnlyIfLength6("Kotlin")) //prints true


fun stringOnlyIfLength6(str: Any): Boolean {
        return str !is String || str.length == 6
}

print(stringOnlyIfLength6("Kotlin")) //prints true

In the above code, in the first function, if the first condition is true, Kotlin type casts the parameter in the second parameter to the same type.

Smart Casts in Classes

Let’s create classes that implement an interface as shown below:


import java.util.*

fun main(args: Array<String>) {
    class Car : Vehicle {
        override fun printDetails() {
            println("AUDI Rocks")
        }
    }
    class Bike : Vehicle {
        override fun printDetails() {
            println("Bullet fires")
        }
    }
    val printMe: Vehicle
    val random = Random()

    fun rand(from: Int, to: Int): Int {
        return random.nextInt(to - from) + from
    }
    printMe = if (rand(0, 10) % 2 == 0) {
        Car()
    } else {
        Bike()
    }
    if (printMe is Car) {
        printMe.printDetails()
    }
    if (printMe is Bike) {
        printMe.printDetails()
    }
}

interface Vehicle {
    fun printDetails()
}

The Random function gets a random integer between 0 to 10. Based on whether it’s even or odd, the interface creates instantiates from either of the classes.

The is operator then calls the method in the if expressions by smart casting the type of the class.

Note: The Kotlin compiler does not smart cast when it cannot guarantee that the value hasn’t changed between check and usage. It always smart casts for val properties and can never do so for var properties.

Explicit Type Casting

We can explicitly type cast properties in Kotlin using the as operator.


val object: Any = "Hello World"
val str: String = object as String
println(str.length)

The as operator is unsafe. It can lead to ClassCastException similar to Java in scenarios shown below.


var y = null
var x = y as String
println(x) // crashes 

x is not a nullable type, so it cannot be set to null. For this case, we’ll can do either of the following:


var y = null
var x = y as String?
println(x)

This allows us to set x as a null.

But the above approach would fail when:


var y = 5
var x = y as String?
println(x) //crashes

So we need to use the as? operator which instead of giving a runtime exception, sets a null value if the cast doesn’t succeed.


var y = 5
var x = y as? String
println(x) //gives a null

That’s all for type checking and smart casting in kotlin programming language.

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages