Pocket Studio Academy
HomePart 11.2

Types: Int, Double, Boolean, String

Free lesson9 min read·4 questions

Every value in Kotlin has a kind — whole number, decimal, yes/no, or text. Kotlin tracks that kind for you and refuses to build code that mixes them up, which turns a whole family of crashes into a red underline you fix in seconds.

The mistake Kotlin will not let you make

A recipe says 200 g of flour and 20 minutes in the oven. Both are numbers. Add them together and you get 220 of absolutely nothing.

Computers have exactly this problem, on a much bigger scale. A phone number, a price, a password and a countdown are all "just data" to the machine. Something has to remember which is which — and in , that something is the language itself.

The kind of a is called its . Every value has one. Kotlin works out what it is, remembers it, and blocks you the moment you try something that makes no sense.

kotlin
1val age = 12
2val name = "Sam"
3println(age - name)   // the compiler refuses this

That is not the being fussy. That is a bug being caught while you are still sitting comfortably, rather than on somebody's phone six months from now.

Think of it like this

Think of a set of kitchen containers.

The measuring jug has millilitres printed up the side. The scales read in grams. The oven timer counts minutes. Each one is built for a single kind of quantity, and that is the whole point: you cannot pour 200 grams, and the jug will never tell you when the cake is done.

Types are those containers. An Int holds a whole number and nothing else. A String holds text and nothing else. The container tells you — and Kotlin — what is allowed to go in, and what you are allowed to do with it once it is there.

The four you will use every day

  • holds whole numbers, positive or negative: 0, 42, -7.
  • holds numbers with a decimal point: 3.5, -0.25, 9.81.
  • holds only true or false. There is no third option.
  • holds text of any length: "Ada", "hello world", or even "", which is text with nothing in it.

Notice the capital letters. Kotlin type names always start with a capital, which is a quick way to spot them in unfamiliar code.

Two details worth pinning down now:

  • 5 and 5.0 are different values of different types. The first is an Int, the second is a Double. A decimal point is not decoration; it changes what the value is.
  • "5" is not a number at all. The quote marks make it text. "5" + "5" gives "55", because gluing text is what + means for strings.

Kotlin usually works the type out for you

You have already written types without noticing:

kotlin
1val lives = 3        // Int
2val speed = 1.5      // Double
3val ready = true     // Boolean
4val name = "Ada"     // String

Kotlin reads the value on the right and works out the type on the left. This is called , and it is why Kotlin feels lighter than older languages without giving up any safety. The type is still fixed. It is still checked on every line. You just did not have to type it.

When you want to be explicit — or when Kotlin genuinely cannot tell — you write the type after a colon:

kotlin
1val lives: Int = 3
2val speed: Double = 1.5
3val ready: Boolean = true
4val name: String = "Ada"

Both forms compile to exactly the same thing. Use the short form for obvious values, and the long form when spelling it out makes the code clearer to a reader.

Careful

A declared type is a promise, and Kotlin checks it immediately:

kotlin
val total: Int = 4.5

This fails with The floating-point literal does not conform to the expected type Int. You promised a whole number and handed over a decimal. Kotlin never quietly rounds behind your back — it stops and asks you what you meant.

Changing type on purpose

Sometimes you really do need a number as text, or an Int as a Double. Kotlin makes you say so out loud, with a conversion function:

kotlin
1val n = 7
2println(n.toDouble())    // 7.0
3println(n.toString())    // "7"
4val d = 2.9
5println(d.toInt())       // 2, not 3

That last line is the one to remember. toInt() chops the decimal off; it does not round. 2.9 becomes 2. If you want rounding you have to ask for it — you will meet Math.round when you need it in Part 5.

The dot in n.toDouble() means "on this value, do this". You will see that dot constantly from here on.

Two more types, briefly

You will meet these occasionally, and it is better to recognise them than to be surprised:

  • — a whole number with far more room than Int. An Int stops at about two billion, which sounds like plenty until you store a time in milliseconds. Write the value with an L on the end: val t: Long = 9000000000L.
  • — exactly one character, in single quotes: val grade: Char = 'A'. A String is any amount of text; a Char is precisely one.

There is also Float, a smaller cousin of Double. Android uses it in places, and Kotlin writes it with an f: 1.5f. Prefer Double in your own code unless something asks for a Float.

Reading the type in an error

Try it in Pocket Studio
  1. Open Pocket Studio, tap Projects, and open the KotlinLab project you made in Lesson 1.1.
  2. Tap Lab.kt to open it in the Editor.
  3. Select everything between the { and } of main and delete it, leaving the empty shell.
  4. Inside main, type four declarations with their types spelled out: val lives: Int = 3, val speed: Double = 1.5, val ready: Boolean = true, val name: String = "Ada".
  5. Add four lines: println(lives), println(speed), println(ready), println(name).
  6. Tap Run. The Output panel shows 3, 1.5, true, Ada — one per line. Notice that 1.5 printed with its decimal point and 3 did not.
  7. Now add println(lives.toDouble()) and run again. The same 3 comes back as 3.0.
  8. Break it deliberately: change val speed: Double = 1.5 to val speed: Int = 1.5 and run. Read the error, then put it back. That error is your friend for the next eighty lessons.
Error Doctor5 common errors
e: Type mismatch: inferred type is String but Int was expected
MeansYou gave text where a whole number was required. "5" with quotes is text; 5 without them is a number.
FixRemove the quote marks if you meant a number. If the value really is text and you need it as a number, convert it explicitly with .toInt().
e: The floating-point literal does not conform to the expected type Int
MeansYou declared something Int and then gave it a value with a decimal point, like 4.5.
FixEither change the declared type to Double, or drop the decimal part. Kotlin will not round for you, because guessing what you meant is how bugs get in.
e: The integer literal does not conform to the expected type String
MeansYou declared a String and gave it a bare number: val id: String = 7.
FixPut quote marks round it — "7" — or convert with 7.toString() if the number is coming from somewhere else.
e: Unresolved reference: toInteger
MeansThat function does not exist. Kotlin's conversions are named after the short type names.
FixUse .toInt(). The family is .toInt(), .toDouble(), .toLong(), .toFloat() and .toString().
e: Conflicting declarations: val name: String, val name: String
MeansYou declared the same name twice in the same place. Kotlin has no way to know which one you mean afterwards.
FixDelete one of them, or rename it. If you meant to change the value, drop the second val — you only declare a name once.
Recap
  • Every value has a : the kind of thing it is. Kotlin checks types on every line and refuses to build code that mixes them nonsensically.
  • The four you will use constantly are (whole numbers), (decimals), (true/false) and (text).
  • means you rarely write the type out — but you can, after a colon, when it makes the code clearer.
  • 5, 5.0 and "5" are three different values of three different types.
  • Convert on purpose with .toInt(), .toDouble() and .toString(). toInt() chops the decimal off; it does not round.
  • Next: text deserves a lesson of its own — building it, slotting values into it, and getting a quote mark inside a quoted string without everything falling apart.