1. Overview

In this tutorial, we’ll look at various ways to convert a variable of type Any to an Int. We’ll see how to do it with unsafe casting. Additionally, we’ll demonstrate converting to String and then to Int.

2. Use Unsafe Cast Operator

The Any type in Kotlin is the root of the type hierarchy. It can hold values of any non-nullable type. This flexibility, however, sometimes requires explicit conversion when we want to work with a specific type, such as Int.

One straightforward way to convert an Any to an Int is by using the unsafe cast operator. While this approach may seem convenient, it comes with some risks and should be used cautiously:

@Test
fun `when casting to Int then it works`() {
    val anyValue: Any = 11
    val intValue: Int = anyValue as Int
    assertThat(intValue).isEqualTo(11)
}

In the above code snippet, we attempt to cast the Any value to an Int. If the actual type of anyValue isn’t an Int, a ClassCastException will be thrown at runtime. This makes the unsafe cast operator suitable only when we’re certain about the type of the Any variable:

@Test
fun `when casting to Int then exception is thrown`() {
    val anyValue: Any = "Not a number"
    assertThrows<ClassCastException> {
        val intValue: Int = anyValue as Int
    }
}

Therefore, it’s recommended to perform type checks before applying the cast to ensure a safe conversion:

@Test
fun `when casting to Int then exception is handled`() {
    val anyValue: Any = "Not a number"
    assertThrows<NumberFormatException> {
        if (anyValue is Int) {
            val intValue: Int = anyValue
        } else {
            throw NumberFormatException("Provided value is not a number")
        }
    }
}

By checking the type using the is operator, we can ensure a safer conversion without risking runtime exceptions.

3. Cast to String and Then to Int

Now, let’s have a look at another approach to convert Any to Int. It involves an intermediate step of converting the Any value to a String and then parsing the String to obtain an Int:

@Test
fun `when converting to Int then it works`() {
    val anyValue: Any = 11
    val stringValue: String = anyValue.toString()
    val intValue = stringValue.toInt()
    assertThat(intValue).isEqualTo(11)
}

In this method, we use the toString() function to convert the Any value to its String representation. After obtaining the string, we use the toInt() function to parse it into an Int.

This approach is more forgiving than the unsafe cast and provides better control over potential errors. The toString() function can be applied to any type and returns the string representation of it. Additionally, conversion from String to Int provides a more controlled way to handle it. Instead of throwing a very general ClassCastException exception, it throws NumberFormatException. This allows us to handle the exception gracefully.

However, it’s crucial to handle cases where the conversion to Int might fail, such as when the Any value doesn’t represent a valid integer:

@Test
fun `when converting to Int then exception is thrown`() {
    val anyValue: Any = "Not a number"
    assertThrows<NumberFormatException> {
        anyValue.toString().toInt()
    }
}

By using a trycatch block, we can gracefully handle situations where the conversion to Int fails due to an invalid format:

@Test
fun `when converting to Int then exception is handled`() {
    val anyValue: Any = "Not a number"
    assertDoesNotThrow {
        try {
            anyValue.toString().toInt()
        } catch (e: NumberFormatException) {
            println("Provided value is not an number")
        }
    }
}

4. Conclusion

In this article, we saw that converting Any to Int in Kotlin requires careful consideration of the data at hand. While the unsafe cast operator provides a concise solution, it comes with the risk of runtime exceptions. On the other hand, converting to String and then parsing to Int offers more control but requires additional error handling.

As always, the source code of the examples is available over on GitHub.