Zum Inhalt springen
Kotlin Anfรคnger 25 min

if, when & Schleifen

Kontrollstrukturen in Kotlin als Ausdruecke, das maechtige when und die verschiedenen Schleifen. Plus: Ranges und destrukturierte for-Schleifen.

Aktualisiert:
Inhaltsverzeichnis

Kontrollstrukturen in Kotlin

Eine Besonderheit, die Kotlin von Java abhebt: Die meisten Kontrollstrukturen sind Ausdruecke, die einen Wert zurueckliefern.

if als Ausdruck

Du kannst if klassisch als Anweisung nutzen:

val alter = 18

if (alter >= 18) {
    println("Volljaehrig")
} else if (alter >= 16) {
    println("Fast volljaehrig")
} else {
    println("Zu jung")
}

Oder als Ausdruck, der einen Wert liefert:

val text = if (alter >= 18) "volljaehrig" else "minderjaehrig"

Das ersetzt den ternaeren Operator (den Kotlin nicht hat) - und ist oft lesbarer.

Bloecke als Ausdruecke

val status = if (alter >= 18) {
    println("pruefe weiter...")
    "volljaehrig"            // letzter Wert ist das Ergebnis
} else {
    "minderjaehrig"
}

when - Kotlins Killer-Feature

when ist das bessere switch - und gleichzeitig ein Ersatz fuer lange if/else-Ketten.

Klassisch (mit Wert)

val tag = "Dienstag"

when (tag) {
    "Montag" -> println("Wochenstart")
    "Dienstag", "Mittwoch", "Donnerstag" -> println("Mitte der Woche")
    "Freitag" -> println("Bald Wochenende")
    else -> println("Wochenende")
}

Kein Fall-Through - jeder Fall endet automatisch.

when als Ausdruck

val beschreibung = when (tag) {
    "Montag" -> "Wochenstart"
    "Dienstag", "Mittwoch", "Donnerstag" -> "Mitte der Woche"
    "Freitag" -> "Bald Wochenende"
    else -> "Wochenende"
}

Der Compiler zwingt dich, alle Faelle abzudecken (wenn du eine Enum oder Sealed Class matchst, kannst du else weglassen, wenn alles abgedeckt ist).

when ohne Argument

Wirkt wie eine if/else-Kette:

val punkte = 85

val note = when {
    punkte >= 90 -> "A"
    punkte >= 80 -> "B"
    punkte >= 70 -> "C"
    punkte >= 60 -> "D"
    else -> "F"
}

Oft lesbarer als verschachtelte if-Statements.

Ranges und Sammlungen

val zahl = 42

val kategorie = when (zahl) {
    in 1..9 -> "einstellig"
    in 10..99 -> "zweistellig"
    in 100..999 -> "dreistellig"
    else -> "sehr gross oder negativ"
}

val liste = listOf(1, 2, 3)
when {
    zahl in liste -> println("in Liste")
    zahl !in liste -> println("nicht in Liste")
}

Type-Checking in when

fun beschreibe(w: Any): String = when (w) {
    is Int -> "Int: $w"
    is String -> "String der Laenge ${w.length}" // Smart Cast!
    is Boolean -> "Boolean: $w"
    is List<*> -> "Liste mit ${w.size} Eintraegen"
    null -> "null"
    else -> "unbekannter Typ"
}

Schleifen

for ueber eine Sammlung

val namen = listOf("Max", "Anna", "Leo")

for (name in namen) {
    println(name)
}

Mit Index

for ((i, name) in namen.withIndex()) {
    println("$i: $name")
}

Ueber Ranges

for (i in 1..10) println(i)          // 1..10
for (i in 1 until 10) println(i)     // 1..9
for (i in 10 downTo 1) println(i)    // 10..1
for (i in 1..10 step 2) println(i)   // 1, 3, 5, 7, 9

Ueber eine Map

val alter = mapOf("Anna" to 28, "Max" to 34)

for ((name, jahre) in alter) {
    println("$name: $jahre")
}

Das ist Destrukturierung - ein Kotlin-Feature, das wir noch ausfuehrlicher kennenlernen.

while und do-while

Klassisch:

var n = 10
while (n > 0) {
    println(n)
    n--
}

// Laeuft mindestens einmal
do {
    print("> ")
    val eingabe = readLine()
    if (eingabe == "exit") break
    println("Du sagtest: $eingabe")
} while (true)

break und continue

for (i in 1..10) {
    if (i % 2 == 0) continue
    if (i > 7) break
    println(i) // 1, 3, 5, 7
}

Labels

Fuer verschachtelte Schleifen:

aussen@ for (x in 0..4) {
    for (y in 0..4) {
        if (x + y == 4) {
            break@aussen
        }
    }
}

try/catch als Ausdruck

Auch try liefert einen Wert:

val zahl = try {
    "123".toInt()
} catch (e: NumberFormatException) {
    0
}

Das macht Fehlerbehandlung kompakter.

Praktisches Beispiel

fun kategorisiere(alter: Int): String = when {
    alter < 0 -> "ungueltig"
    alter < 18 -> "Kind"
    alter < 65 -> "Erwachsen"
    else -> "Senior"
}

fun main() {
    val alter = readLine()?.toIntOrNull() ?: run {
        println("Bitte eine Zahl eingeben")
        return
    }

    println("Mit $alter Jahren: ${kategorisiere(alter)}")
}
  • ?: mit run { ... } als Elvis-Block - elegant fuer Fehlerbehandlung
  • when { ... } ersetzt if/else in Kaskaden
  • kategorisiere nutzt die Ein-Ausdruck-Syntax mit =

Zusammenfassung

  • if und when sind in Kotlin Ausdruecke - sie liefern Werte
  • when mit Argument matcht Werte, ohne Argument ist es eine if/else-Kette
  • when kann Ranges (in 1..10), Typen (is String), Listen (in liste) pruefen
  • for in ueber Collections, Ranges, Maps - alles idiomatisch
  • Labels fuer verschachtelte break / continue
  • Sogar try kann als Ausdruck genutzt werden

Im naechsten Kapitel: Funktionen und Lambdas - Kotlins Fundament fuer funktionalen Code.

Zurรผck zum Kotlin Kurs