skip to content

How Kotlin Does Basic Syntax

How familiar syntax concepts land in Kotlin specifically: if, when, and try produce values instead of just branching, semicolons disappear, and val is the default binding. Interviewers use this as a warm-up to see whether you write Kotlin idiomatically or Java with different keywords.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

questions

5

How does Kotlin's if differ from Java's if, and what does it mean that if is an expression?

level: juniorimportance: must knowfreq 80%

answer

  1. if is an expression — it returns a value
  2. No ternary operator in Kotlin (use if/else)
  3. As an expression, else is mandatory
  4. Branch value = last expression of the block
  5. Result type = least common supertype of branches

basics

~10 s

In Kotlin, if can produce a value, so you can assign its result to a variable. Because of that, Kotlin has no separate ternary (?:) operator — you just use if/else.

solid answer

~40 s

In Kotlin, `if`/`else` is an **expression**: it evaluates to a value, which you can assign or return directly. The value is the last expression of the chosen branch (use a block with the result as its final line). Because `if` already returns a value, Kotlin deliberately has no ternary `cond ? a : b` operator. When used as an expression, the `else` branch is mandatory, otherwise the result could be undefined. The resulting type is the least common supertype of the branch values. `if` can also be used as a plain statement (no value used), exactly like Java, when you just run side effects. This expression-orientation is shared by `when` and `try`, and pairs naturally with single-expression functions: `fun max(a: Int, b: Int) = if (a > b) a else b`.

code

kotlin · 7 lines
kotlin
fun describe(n: Int): String = if (n > 0) {
    "positive"
} else if (n == 0) {
    "zero"
} else {
    "negative"   // else required because if is used as an expression
}

go deeper

for a junior

Knows if returns a value and that there's no ternary operator.

for a middle

Explains why else is mandatory as an expression and how block branches yield their last line.

for a senior

Discusses resulting-type unification (least common supertype) and use in single-expression functions.

for a principal

Frames expression-orientation as a consistent language design choice spanning if/when/try that reduces temporary statements and improves composability.

## Statement vs expression - A **statement** performs an action and yields no usable value. - An **expression** evaluates to a **value** you can assign, return, or pass. In Java, `if` is only a statement, which is why Java needs the ternary operator `cond ? a : b` to choose a value inline. In Kotlin, `if` is an **expression**, so it can directly produce a value: ```kotlin val max = if (a > b) a else b // if yields a value ``` Because `if` already does this job, **Kotlin has no ternary operator** — there is no `?:` for conditionals (note: `?:` in Kotlin is the unrelated *Elvis* operator for null-defaulting). ## The else branch becomes mandatory When `if` is used **as an expression**, you must supply `else`, because every path needs to yield a value: ```kotlin val label = if (n > 0) "pos" else "non-pos" // else required ``` Used purely as a statement (its value ignored), `else` is optional: ```kotlin if (n > 0) println("positive") // no else needed ``` ## Blocks and the resulting value A branch can be a block; its **last expression** is the branch's value: ```kotlin val sign = if (n >= 0) { log("non-negative") "+" // this is the value of the branch } else "-" ``` ## Resulting type The type of the whole `if` expression is the **least common supertype** of the branch values. If branches return `Int` and `Int`, the result is `Int`; if `String` and `Int`, it widens toward `Any`/`Comparable`. ## Single-expression functions Expression `if` shines with `=`-bodied functions: ```kotlin fun max(a: Int, b: Int) = if (a > b) a else b ``` This same expression model also applies to `when` and `try`.

  • Why does Kotlin not have a ternary operator?
    Because if/else is already an expression that returns a value, the ternary would be redundant. The language designers removed it deliberately.
  • When is else optional with if?
    When if is used as a statement and its value is discarded. As an expression (assigned or returned), else is required.

Java's if is a vending machine that only dispenses (statement); Kotlin's if is one that also hands you back change you can use (a value).

saying these in an interview costs you the question

  • Looking for a ?: ternary operator for conditionals
  • Saying if never returns a value like in Java
  • Omitting else when using if as an expression
  • Confusing the Elvis operator ?: with a ternary
  • Not knowing the branch value is the block's last line

context

open as a page

What is the difference between val and var in Kotlin, and why is val-first considered idiomatic?

level: juniorimportance: must knowfreq 90%

basics

~10 s

val makes a read-only reference you can't reassign; var makes a reassignable one. Kotlin prefers val first because it makes code safer and easier to reason about.

open as a page

Explain Kotlin's when as an expression: its forms, exhaustiveness rules, and how it replaces switch.

level: middleimportance: must knowfreq 78%

basics

~10 s

when is Kotlin's flexible replacement for switch. It can return a value, match ranges or types, and needs to cover every case (be exhaustive) when used as an expression.

open as a page

How is try a value-producing expression in Kotlin, and how do optional semicolons and statement termination work?

level: middleimportance: should knowfreq 55%

basics

~10 s

Kotlin's try/catch can return a value you assign to a variable. Semicolons are optional because newlines end statements; you only need them to put two statements on one line.

open as a page

Why does Kotlin make if/when/try expressions instead of statements, and what design trade-offs come with leaning on this?

level: seniorimportance: should knowfreq 40%

basics

~10 s

Making control structures return values lets you assign results directly and skip temporary mutable variables, leading to shorter, safer code. Overusing it, though, can make logic hard to read.

open as a page