Alles ist ein Ausdruck
if, when und try geben in Kotlin Werte zurück, also gibt es keinen Ternary-Operator und keinen Temporär-dann-Zuweisen-Tanz - und when ist ein weit mächtigeres switch.
Deutsche Übersetzung in Arbeit
Diese Lektion ist noch nicht ins Deutsche übersetzt und wird daher auf Englisch angezeigt. Der Rest der Seite ist vollständig lokalisiert.
Auf dieser Seite
Here's a shift that quietly changes how you write code: in Kotlin, control-flow constructs are expressions -
if, when, and try return values. Java draws a hard line between statements (things that do something) and
expressions (things that have a value); Kotlin erases much of it. The practical upshots are no ternary operator
(you don't need one), no "declare-then-assign-in-each-branch" dance, and when - a switch so much better it
deserves its own introduction.
if is an expression
In Java, if is a statement, so to compute a value conditionally you either use the ternary ?: or declare a
variable and assign it in each branch. In Kotlin, if itself yields a value:
val max = if (a > b) a else b // if returns a value - no ternary needed
val label = if (score >= 90) { // branches can be blocks; the LAST expression is the value
"excellent"
} else if (score >= 60) {
"pass"
} else {
"fail"
}Because if/else produces a value, Kotlin has no ternary operator - it would be redundant. And you avoid the
common Java pattern of String label; if (...) label = ...; else label = ...; - just assign the if expression
directly to a val. (Note: for if to be an expression, an else is required - there must be a value in every
case.)
when: switch, evolved
when is Kotlin's replacement for switch, and it's dramatically more capable. As an expression, it returns a
value; and it matches far more than constants:
val description = when (x) {
0 -> "zero" // constant match
1, 2, 3 -> "small" // multiple values in one branch
in 4..10 -> "medium" // a RANGE
is String -> "it's a string" // a TYPE check (with smart cast)
else -> "large" // else is required when used as an expression
}when can match constants, multiple values, ranges (in 4..10), type checks (is String - and it smart-casts,
so inside that branch x is a String), and even arbitrary conditions when you omit the subject:
val grade = when { // no subject: each branch is a boolean condition
score >= 90 -> "A"
score >= 80 -> "B"
else -> "F"
}Compare Java's switch: no fall-through bugs (no break needed - branches don't fall through), no restriction to
constants, and it returns a value. It's closer to Java's newer switch expressions and pattern matching, but it
arrived earlier and is used everywhere in idiomatic Kotlin.
try is an expression too
Even try/catch returns a value, which is occasionally elegant:
val number = try {
input.toInt() // the value if it succeeds
} catch (e: NumberFormatException) {
0 // the value if it fails
}Why this matters: fewer temporaries, more val
The cumulative effect of expression-oriented control flow is that you assign the result of a decision directly
to an immutable val, instead of declaring a mutable var and mutating it across branches. That reinforces the
val-by-default habit from the last lesson: expressions let you compute-then-bind, so more of your variables can
be read-only. Less mutation, fewer temporaries, and code that reads as "this value is the result of this
decision."
Exhaustive when on sealed types is compiler-checked
when becomes especially powerful over a sealed type or enum: if you cover every case, you don't need an else, and if you later ADD a case, the compiler flags every when that no longer handles all of them. That's exhaustiveness checking - the same algebraic-data-type benefit from the advanced Java module, and a reason when + sealed classes (next module) is a favorite Kotlin pattern for modeling states safely.
Java statements are like a vending machine that, when you press a button, merely does something internally - you
then have to go check a separate slot to see what happened (declare a variable, inspect it after). Kotlin
expressions are a machine that hands you the item directly the moment you choose: assigning
val snack = when(choice) ... - the selection immediately becomes the thing you hold. You don't press a button and then rummage; the act
of deciding is the act of producing the value. when is the deluxe machine that also accepts ranges of coins,
groups of buttons, and 'anything sweet' as a selection - far more than the old model's one-button-one-item
switch - and it never accidentally dispenses two snacks because you forgot a break.
Convert this Java to idiomatic Kotlin using expressions and when: a method that takes an int httpStatus and returns a String category - 200-299 → 'success', 300-399 → 'redirect', 400-499 → 'client error', 500-599 → 'server error', anything else → 'unknown'. The Java version declares a String result, uses if/else-if, and returns it. Make the Kotlin as tight as idiomatic style allows.
What does it mean that if, when, and try are expressions in Kotlin?
Key takeaways
- In Kotlin, if, when, and try are expressions that return values, so you assign the result directly to a val.
- Because if returns a value, Kotlin has no ternary operator, and you avoid the declare-then-assign-per-branch pattern (an else is required for if used as an expression).
- when replaces switch and is far more capable: it matches constants, multiple values, ranges (in 4..10), and type checks (is String, with smart cast), and returns a value.
- when has no fall-through (no break) and can be subject-less, where each branch is a boolean condition - a cleaner if/else-if chain.
- Expression-oriented control flow reinforces val-by-default (compute then bind) and, over sealed types/enums, gives compiler-checked exhaustiveness.