1 minute read

Kotlin introduced handy operator called when instead of switch in Java.

when (x) {
    1 -> print("x == 1")
    2 -> print("x == 2")
    else -> { // Note the block
        print("x is neither 1 nor 2")
    }
}

It’s pretty straightforward how to use when in Kotlin and looks clean and simple.

Let’s take another example a little bit more advanced then just a numbers. Imagine that you have two classes Foo and Bar inherited from Foo:

open class Foo {}

class Bar: Foo() {}

Let’s write a function which will return a string message based on instance of a class.

fun getFooOrBar(fooOrBar: Foo): String {
    return when (fooOrBar) {
        is Foo -> "Foo"
        is Bar -> "Bar"
        else -> "Unknown"
    }
}

And call getFooOrBar()  function with Bar instance

println(getFooOrBar(Bar()))

What do you think will be printed? Right, the result will be “Foo” not “Bar”.

Here’s what happened here. Bar is a child of Foo and is operator will conform that Bar instance of Foo. In when operator as soon as branch condition satisfied it will return string value and stopped working (which is expected).
In other words first condition will be satisfied hence result will be “Foo” for Bar instance.

Luckily in that case Intellij IDEA gave us a proper warning: Warning

But now always.
When you use instances of Java classes in when operator you will not see any warnings. Warning

And if you call the function in example above:

println(getMessageForException(UnknownHostException()))

Result will be “IOException” message.

Conclusion

Sequence does matter when you use when and is operators.
Don’t always trust on your IDE.

Here’s a full gist that you can try yourself, in case if you don’t trust me :)