1. Why do we need type conversion?
Kotlin is a strictly (statically) typed language. If a computer has a “little box” for a number, then trying to shove text in there is roughly the same as trying to plug a fork into a USB port. The compiler will not forgive you for that! 😡
However, in real life we often work with different data types at the same time. For example, you have a string that contains a number. That is exactly where conversion (or transformation) of types is needed.
Let’s look at an example. Suppose you want to store the number of users:
val a: Int = 1
val b: Int = "2"
val c: Int = "three"
The compiler will immediately say: “Who do you think I am? I can’t automatically convert a string to a number. I need you to do it explicitly.”
In Kotlin there are several ways to convert values, and each one has its own pros, cons, and typical pitfalls.
2. Converting Int to String
In practice, you often need a string representation of a number: for example, to display it on screen, save it to a file, send it over the network, concatenate it with text, etc. In Kotlin there are several ways to do this, and each one is convenient in different situations.
The toString() function
This is the main and most common approach:
val number = 42
val str = number.toString() // str == "42"
toString() converts a value into a string representation appropriate for that value’s type.
Concatenation with an empty string
An old but working approach:
val number = 42
val str = "" + number
This approach works quickly for simple cases, but it is less explicit for someone reading the code.
3. Implicit conversion to string
As mentioned above, the Kotlin developers made it so that absolutely all variables, objects, and expressions in Kotlin can be converted to the String type.
Moreover, this happens automatically when we add a String to some other type. Examples:
val a = 5
val name = "Anya" + a // name contains the string Anya5
val a = 5
val city = a + "New York" + a // city contains the string 5New York5
val number = 10
val code = "Yo"
val message = "Hello! " + number + code // message contains the string Hello! 10Yo
In all three examples, we calmly added variables of types Int and String, and the result was always a String.
Examples:
val a = 5
val name = "1" + a // name contains the string 15
val a = 5
val city = a + "9" + a // city contains the string 595
val number = 10
val code = "10"
val message = "" + number + code // message contains the string 1010
The addition operation is performed left to right, so the result can be somewhat unexpected. Example:
val a = 5
val name = a + a + "1" + a // name contains the string 1015
Order of evaluation: ((a + a) + "1") + a
4. Converting a string to a number: toInt()
To convert a number to a string in Kotlin, it is enough to add it to an empty string:
val str = "" + number
But what if you need to convert a string to a number? You can’t convert just any string into a number. However, if the string contains only digits, then you can. For this, Kotlin has a special function.
This command looks like this:
val x: Int = str.toInt()
Where val x: Int is the declaration of an integer variable x, and str is a number given as a string (a string consisting of digits).
Examples:
val str = "123"
val number1 = str.toInt() // number1 contains the number 123
val number2 = "321".toInt() // number2 contains the number 321
val number3 = ("321" + 0).toInt() // number3 contains the number 3210
val number4: Int = "321" // Won't compile: variable type is Int, but the value type is String
This also works for negative values: the toInt() function is very smart.
5. toIntOrNull(): safe conversion to a number
When a string comes from the outside world (from a file or from a user), there is always a risk that it is not a number. That is where a safer method comes in: toIntOrNull().
It works like this: if the string really contains an integer, it returns an Int. If not, it returns null. This is fundamentally different behavior compared to toInt(): instead of a runtime error and the program crashing, we get a special value — null.
null is a special value that means “there is no value”. That is, null is not 0, not an empty string, and not an “error message as text”. It is exactly “no result”.
Extending the Int type: Int?
The Int type stores only valid integers; it cannot store strings, fractional numbers, and it cannot store null either. That is why Kotlin has an extended version of the Int type — Int?. It stores all values of type Int and the value null (no value).
This situation is so common that Kotlin made it part of the language: you can add a question mark to any type in Kotlin and get an “extended type” that can also store null.
If a regular Int always stores a number, then Int? is read as: “either Int or null”. The question mark is literally a marker meaning “may be absent”.
The toIntOrNull() method returns Int? because it may successfully parse a number, or it may fail to parse it.
Mini-example: successful and unsuccessful parsing
It is very useful to see what happens in both cases right now, instead of trying to “guess”.
fun main() {
val ok: Int? = "15".toIntOrNull()
val bad: Int? = "15a".toIntOrNull()
println(ok) // 15
println(bad) // null
}
6. Cheat sheet and conversion practice
When there are several methods, your brain asks for a “cheat sheet”. That’s normal: you are not required to keep everything in your head — you are required to be able to quickly restore the meaning.
Reference table: toString() vs toInt() vs toIntOrNull()
| Method | From → to | When to use | What happens if the string is not a number |
|---|---|---|---|
|
|
you need to display/concatenate text | not applicable (we’re converting from a number) |
|
|
you are sure the string is valid | runtime error (exception) |
|
|
the string may be “messy” | returns null |
Why Kotlin forces you to be explicit
When people first encounter explicit conversions, there is a desire: “Why doesn’t the language figure out by itself that "123" is a number?” But the language specifically does not want to guess.
Imagine you wrote "007". Is that the number seven? Or is it a department code? Or is it a string where leading zeros are important? If the language starts automatically turning strings into numbers, it will constantly guess wrong. Kotlin chooses predictability: if you want a number, call toInt() or toIntOrNull() and take responsibility yourself.
And, in fact, that’s a very mature stance for a language. Kotlin is basically saying: “I’m not a telepath. I’m a compiler.”