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
Answer
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
agevariable not ambiguous? - Why is one of the variables defined with
valand the other withvar?
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.
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.
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.
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.