val, var and basic types

Kotlin · Essentials · 10 min

Preferring val and understanding Kotlin's type system is the foundation of idiomatic Kotlin.

Kotlin has two kinds of variables:

  • val is read-only: assigned once, like Java's final. Prefer it by default.
  • var is mutable and can be reassigned.

Types are usually inferred: val count = 3 is an Int, val price = 9.99 a Double. Declare explicitly with a colon: val ratio: Float = 0.5f. The type is fixed at compile time either way.

Basic types:

  • Integers: Byte, Short, Int (default), Long (3L). Unsigned UInt, ULong exist too.
  • Floating point: Double (default), Float (1.5f).
  • Boolean, Char ('a'), String.

All of them are objects with methods (5.toString(), 3.coerceAtLeast(5)), but the compiler uses JVM primitives under the hood where possible, so there's no performance penalty.

Kotlin does no implicit widening between numeric types: an Int can't be assigned to a Long variable without toLong(). Use toInt(), toDouble() and friends. Integer division truncates (7 / 2 == 3); % is remainder. Readable literals use underscores: 1_000_000.

const val declares a compile-time constant at top level or in an object. Note that val makes the reference read-only, not the object: a val list = mutableListOf(1) can still be modified with add.

Example

const val MAX_USERS = 100

fun main() {
    val name = "Ada"            // String, read-only
    var age = 36                // Int, mutable
    age += 1
    val big: Long = 3_000_000_000
    val ratio = 7 / 2           // Int division
    val exact = 7 / 2.0         // Double
    println("$name $age $ratio $exact")   // Ada 37 3 3.5

    val i = 42
    val l: Long = i.toLong()    // no implicit widening
    println(l + big)            // 3000000042
    println(MAX_USERS.coerceAtMost(50))   // 50

    val list = mutableListOf(1)
    list.add(2)                 // the val reference is fixed, contents are not
    println(list)               // [1, 2]
}

Remember

  • Use val by default, var only when reassignment is needed
  • Types are inferred but static
  • No implicit numeric widening: call toLong(), toDouble()...
  • val makes the reference read-only, not the object

Watch out for

  • Assuming val list = mutableListOf() is immutable.

Check yourself

  1. Which line compiles? (x is an Int)

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: kotlinlang.org/docs/basic-types.html