Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Defining Variables in Kotlin

You introduce a variable into Kotlin code by using either the val or var keyword, followed by the name of the variable, followed by an assignment operation that gives it a value:

val name = "Nick"
var age = 42

Question

What are the types of name and age in this code?

Answer

name is a String, and age is an Int.

Note: you must use this exact spelling for the type names. Kotlin is case-sensitive, like most programming languages.

The code example above raises some important questions:

  • Why do we not need to specify types for either of these variables?
  • Why is the type of the age variable not ambiguous?
  • Why is one of the variables defined with val and the other with var?

Read on for answers to these questions…

Type Inference

Like C, Kotlin requires that a variable has a type that is known at compile time. However, unlike C, Kotlin can often infer what that type should be, freeing us from the need to specify it explicitly. This gives Kotlin some of the lightweight feel of a dynamically-typed language like Python.

Consider the two examples from earlier. These could be written more explicitly as

val name: String = "Nick"
var age: Int = 42

However, we do not need to be this explicit. Kotlin can infer that name is a String because the value we are assigning to name consists of characters enclosed in double quotes.

Similarly, Kotlin can infer that age should be of type Int because we are assigning to it a value that consists solely of digits.

Note that type inference in the second example is not ambiguous, despite the fact that Kotlin has a number of different integer types. This is because integer literals consisting only of digits are always regarded as Int values.

If you want an integer literal to be regarded as an unsigned value, you must append a u or U to it. If you want it to be regarded as a long integer, you must append an L to it. These can be combined: thus, 42uL will be regarded as an unsigned long integer.

Floating-point literals are also not ambiguous. A value like 3.5 is treated as a Double. If you want it to be treated as a Float, you must append f or F to it.

Caution

Sometimes, you have to specify types explicitly.

For example, Kotlin doesn’t provide special syntax to indicate that an integer literal should be represented as a Short or Byte value, so in those cases you will need to indicate explicitly the type of the variable that will hold such a value.

Another example is function definitions. When defining a function that has parameters, you must always specify the types of those parameters.

val or var?

Both val and var introduce named variables into a program, but it’s important to understand the difference between these two kinds of variable.

When you define a variable with val, you are allowed to assign a value to it once, and once only. Any subsequent attempt at assignment will cause a compile-time error.

When you define a variable with var, you can assign a value to it as many times as you like.

Here’s an example:

val name = "Nick"
name = "Joe"       // compiler error

var age = 42
age = 43           // ok

Why Bother With val?

Wouldn’t it be easier to just define everything as a var?

In practice there are many situations in programming where we give a name to a value purely so that we can use it later in a program, and not because we need to update that value. Then there are other situations where we do need to update the value. Kotlin gives us syntax to distinguish explicitly between these two different ways of using variables.

The advantage of being explicit is that the compiler can then help us catch some programming errors. For example, suppose you have a program that defines a variable amount as a val and another variable newAmount as a var. At a later point in the code, you intend to update the value of newAmount but accidentally type the variable’s name as amount. This will lead to a compiler error, because you are attempting to assign a new value to a val. If you had defined both variables using var, the program would compile but would now have a bug in it—one that might be hard to find and fix.

Tip

The recommended approach in Kotlin is to define variables using val wherever you can. Use var only in those specific cases where a variable will need to be reassigned a value after it has initially been created.

Caution

Don’t think that using val is the same as defining a constant in your code!

When you use val, all you are doing is establishing a permanent link between an object and the name that you want to use to refer to that object. The compiler will stop you associating the name with a different object, but it won’t stop that object from changing its state, should that be possible for the object in question.

For example, you might have a val that is referencing an array of numbers. The compiler will be happy for you to replace the contents of that array with new values. What it won’t let you do is reuse that variable to refer to a different array of numbers.