Variables and values.
Every program works with data. That data needs names. We call these names variables. Today we learn how Kotlin handles variables and the important distinction between values and variables.
A variable is a named container for data.
You give it a name. You put a value in it. Later, you use the name to access the value.
Variables connect names to values. When your code says "count", the runtime knows what count means because you defined it.
In Kotlin, declaring a variable looks like this: a keyword, then the name, then optionally the type, then the value.
But not all containers are the same. Some can be changed. Some cannot. Kotlin makes this distinction explicit.
The keyword val declares an immutable reference.
Once you assign a value to a val, you cannot reassign it. The name is bound to that value permanently.
val count equals 10. Later you cannot write count equals 20. The compiler rejects it.
This is the preferred way to declare most variables in Kotlin. Why? Because immutability makes code easier to understand. You see a val, you know it will not change. You can trust it.
When you read code with val everywhere, you know the values are stable. No surprises. No hunting for where a value was changed.
val does not mean the value itself is immutable. If you have val list equals a mutable list, you cannot reassign list to a different list, but you can add items to the list. The reference is fixed. The content might not be.
The keyword var declares a mutable reference.
You can reassign a var to a new value. var count equals 10. Later count equals 20 is allowed.
Use var when you genuinely need to change a variable's value. Loop counters. Accumulators. State that updates.
But use var sparingly. Every var is a potential source of confusion. Reading code, you must track how the value changes. It makes reasoning harder.
Ask yourself: does this truly need to change? Often you can restructure code to use val instead. A function that computes a result rather than accumulating in a var. A new val for each step rather than modifying one var.
Start with val. Switch to var only when necessary.
Kotlin infers types when possible.
val name equals "Alice". What type is name? String. The compiler knows because you assigned a string literal.
val count equals 42. Type is Int. The compiler infers it.
You do not need to write val name colon String equals "Alice". The type is obvious from the value. Kotlin lets you omit it.
This reduces boilerplate. Your code is shorter. But the type is still there. The compiler knows it. The IDE shows it. You just did not need to write it.
Type inference is not guessing. The compiler deduces the type with certainty. If it cannot, it asks you to provide the type.
Sometimes you need or want to write the type explicitly.
When there is no initial value. val name colon String. You declare the type because there is no value to infer from. You will assign it later.
When you want a specific type. val ratio equals 3.0 gives Double. But if you want Float, you write val ratio colon Float equals 3.0f.
When clarity helps readers. Complex expressions might benefit from stating the type explicitly so readers understand immediately.
When the API requires it. Function parameters always need explicit types. The compiler cannot infer parameter types.
The syntax is: name colon Type. Put the type after the name, separated by a colon.
Some values are truly constant. They never change and are known at compile time.
const val declares a compile-time constant.
const val PI equals 3.14159. This value is embedded directly into the code. No variable lookup at runtime. Maximum performance.
const val has restrictions. It must be a primitive type or String. It must be initialized with a constant expression. It cannot be a computed value.
const val must be at the top level or in an object. It cannot be inside a function.
Use const val for true constants: mathematical values, configuration strings, fixed limits. These are values that are the same everywhere, always.
For values computed once at startup, use regular val. For true compile-time constants, use const val.
Variables have scope. A variable exists within a certain region of code.
A variable declared inside a function exists only in that function. Code outside cannot see it.
A variable declared inside an if block exists only in that block.
Kotlin uses lexical scoping. The position where you declare the variable determines where it is visible.
Keep variables in the narrowest scope possible. Declare them where you first need them, not at the top of the function. This makes code clearer. The variable exists only where it is relevant.
Names matter.
Kotlin uses camelCase for variables and functions. The first word is lowercase, subsequent words are capitalized. userName, totalCount, isValid.
Constants in UPPER_SNAKE_CASE. MAX_SIZE, DEFAULT_TIMEOUT.
Choose meaningful names. count is better than c. userName is better than s. The name should explain the purpose.
Avoid abbreviations unless they are universally understood. id, url, http are fine. usrNm is not.
Good names make code readable without comments.
Let us summarize.
val declares an immutable reference. Once assigned, it cannot be reassigned. Prefer val.
var declares a mutable reference. It can be reassigned. Use only when necessary.
Type inference lets you omit types when the compiler can figure them out.
Explicit types are needed for parameters, when there is no initializer, or for clarity.
const val declares compile-time constants.
Keep scope narrow. Name variables clearly.
Variables are simple, but using them well makes code clearer.