Kotlin Variables
A variable is a named storage location in memory. Think of it as a labeled box — you put data inside the box and use the label to access it later. Kotlin gives you two kinds of boxes: val (sealed box) and var (open box).
val vs var
┌───────────────────────────────────────────────┐
│ val = Value (Read-Only / Immutable) │
│ │
│ Think: A sealed envelope │
│ Once you write inside, you cannot change it │
│ │
│ val age = 25 │
│ age = 30 ← ERROR! Cannot reassign val │
├───────────────────────────────────────────────┤
│ var = Variable (Read-Write / Mutable) │
│ │
│ Think: A whiteboard │
│ You can erase and write a new value anytime │
│ │
│ var score = 100 │
│ score = 200 ← OK! var can be reassigned │
└───────────────────────────────────────────────┘
Declaring Variables
// val: value that does not change
val name = "Alice"
val pi = 3.14159
// var: value that can change
var temperature = 22
temperature = 30 // updating the temperatureWhy Prefer val Over var?
Using val by default prevents accidental changes to data. A variable that cannot change is easier to reason about — you always know its value stays the same. Kotlin developers use val for most things and only switch to var when they specifically need to update a value.
Variable Naming Rules
- Names start with a letter or underscore, never a number.
- Names can contain letters, digits, and underscores.
- Names are case-sensitive.
- Use camelCase for multi-word names:
firstName, notfirstnameorfirst_name.
// Valid names
val userName = "Bob"
val _count = 0
val total2024 = 5000
// Invalid names
// val 2count = 10 ← starts with a number
// val user-name = "" ← hyphen not allowedExplicit Type Declaration
Kotlin can detect the data type automatically. But you can also declare the type explicitly using a colon after the name:
val city: String = "Tokyo"
var population: Int = 14000000
val isCapital: Boolean = trueDeclaring Without Assigning
Sometimes you declare a variable first and assign the value later. In that case, you must provide the type explicitly:
val greeting: String // declared but not assigned yet
// ... some logic here ...
// greeting = "Hello" // ← you must assign before using it
var counter: Int
counter = 0
println(counter) // 0Variable Lifecycle Diagram
val price: Int = 500
│ │ │
│ │ └── Value assigned: 500
│ └── Type: Int (whole number)
└── Keyword: val (cannot change)
─────────────────────────────
var stock: Int = 100
│ │ │
│ │ └── Value assigned: 100
│ └── Type: Int
└── Keyword: var (can change)
stock = stock - 1 → stock is now 99
stock = stock - 1 → stock is now 98
Constants with const val
For values that are truly fixed at compile time (like mathematical constants or configuration values), use const val at the top level of a file or inside an object:
const val GRAVITY = 9.8
const val APP_VERSION = "1.0.0"
fun main() {
println("Gravity: $GRAVITY")
}const val only works with basic types like String, Int, Double, and Boolean. Regular val works with any type including objects and collections.
Practical Example
fun main() {
val productName = "Laptop" // never changes
val taxRate = 0.18 // never changes
var price = 50000 // can change with discounts
println("Product: $productName")
println("Original price: $price")
price = 45000 // discount applied
val tax = price * taxRate
val total = price + tax
println("Discounted price: $price")
println("Tax: $tax")
println("Total: $total")
}Output:
Product: Laptop
Original price: 50000
Discounted price: 45000
Tax: 8100.0
Total: 53100.0