if, when & Schleifen
Kontrollstrukturen in Kotlin als Ausdruecke, das maechtige when und die verschiedenen Schleifen. Plus: Ranges und destrukturierte for-Schleifen.
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)}")
}
?:mitrun { ... }als Elvis-Block - elegant fuer Fehlerbehandlungwhen { ... }ersetztif/elsein Kaskadenkategorisierenutzt die Ein-Ausdruck-Syntax mit=
Zusammenfassung
ifundwhensind in Kotlin Ausdruecke - sie liefern Wertewhenmit Argument matcht Werte, ohne Argument ist es eine if/else-Kettewhenkann Ranges (in 1..10), Typen (is String), Listen (in liste) pruefenfor inueber Collections, Ranges, Maps - alles idiomatisch- Labels fuer verschachtelte
break/continue - Sogar
trykann als Ausdruck genutzt werden
Im naechsten Kapitel: Funktionen und Lambdas - Kotlins Fundament fuer funktionalen Code.