Zum Inhalt springen
Kotlin Anfรคnger 20 min

Dein erstes Kotlin-Programm

Der Aufbau eines Kotlin-Programms: main-Funktion, println, String-Templates und die ersten idiomatischen Patterns.

Aktualisiert:
Inhaltsverzeichnis

Dein erstes Kotlin-Programm

Zeit, das โ€œHallo Weltโ€ zu zerlegen und weiter auszubauen.

Die minimale Kotlin-Datei

fun main() {
    println("Hallo, Kotlin!")
}

fun main()

  • fun leitet eine Funktion ein
  • main ist der Einstiegspunkt
  • Keine Klammern mit Parametern noetig (aber moeglich: fun main(args: Array<String>))

println

Gibt einen Text mit Zeilenumbruch aus. Verwandte Funktion: print ohne Zeilenumbruch.

Kommentare

// Einzeiliger Kommentar

/*
 Mehrzeiliger
 Kommentar
 */

/**
 * KDoc fuer Dokumentation
 */
fun beispiel() { }

String-Templates

Kotlin hat eine elegante Variable-in-String-Syntax:

val name = "Anna"
val alter = 28

println("Hallo, $name!")
println("Du bist $alter Jahre alt.")

// Mit Ausdruecken: ${...}
println("Naechstes Jahr bist du ${alter + 1}.")

$name reicht fuer einfache Variablen, ${...} fuer Ausdruecke.

Semikolons

Kotlin braucht keine Semikolons am Zeilenende. Du kannst sie nutzen, um mehrere Anweisungen auf eine Zeile zu packen:

val a = 1; val b = 2; println(a + b)

Aber: Nimmโ€™s als einzeilig, wenn es nicht noetig ist.

Nutzereingabe

fun main() {
    print("Wie heisst du? ")
    val name = readLine()
    println("Hallo, $name!")
}

readLine() liefert String? - ein nullable String. Wenn das Programm keine Eingabe bekommt, ist das Ergebnis null.

Sicher unwrappen

val name = readLine() ?: "Fremder"
println("Hallo, $name!")

Der ?: (Elvis-Operator) liefert den Default, wenn die linke Seite null ist.

Ein laengeres Beispiel

fun main() {
    val namen = listOf("Max", "Anna", "Leo")

    for (name in namen) {
        if (name.length > 3) {
            println("Hallo, $name!")
        }
    }
}

Funktionaler Stil

fun main() {
    val namen = listOf("Max", "Anna", "Leo")

    namen
        .filter { it.length > 3 }
        .forEach { println("Hallo, $it!") }
}
  • filter, forEach sind higher-order functions auf Collections
  • it ist das implizite Argument der Lambda (bei nur einem)
  • Das { ... } nach einer Funktion ist Trailing Lambda - kein spezieller Syntax

Einfache Funktionen

fun addieren(a: Int, b: Int): Int {
    return a + b
}

// Ein-Ausdruck-Funktion
fun addiere2(a: Int, b: Int): Int = a + b

// Mit Typ-Inferenz
fun addiere3(a: Int, b: Int) = a + b

fun main() {
    println(addieren(3, 4))
}

Kotlin zieht den Rueckgabetyp aus dem einzelnen Ausdruck ab.

Praktisches Beispiel: Kleines Menue

fun main() {
    print("Dein Alter: ")
    val alterText = readLine()
    val alter = alterText?.toIntOrNull() ?: 0

    val status = when {
        alter < 0 -> "ungueltig"
        alter < 18 -> "minderjaehrig"
        alter < 65 -> "volljaehrig"
        else -> "Rentner*in"
    }

    println("Mit $alter Jahren bist du $status.")
}

Was hier spannend ist:

  • alterText?.toIntOrNull() - Safe Call plus gueltige Konvertierung ohne Exception
  • ?: 0 - Default, falls null
  • when { ... } - maechtigere Variante von if/else if

Datenklassen - nur ein Vorgeschmack

data class Produkt(val name: String, val preis: Double)

fun main() {
    val brot = Produkt("Vollkornbrot", 2.99)
    val copy = brot.copy(preis = 3.49)

    println(brot)   // Produkt(name=Vollkornbrot, preis=2.99)
    println(copy)   // Produkt(name=Vollkornbrot, preis=3.49)
    println(brot == Produkt("Vollkornbrot", 2.99)) // true
}

Das alles ohne einen einzigen Getter oder toString-Override zu schreiben. Warum? data class generiert das alles automatisch.

Exit-Codes

import kotlin.system.exitProcess

fun main(args: Array<String>) {
    if (args.isEmpty()) {
        System.err.println("Bitte einen Namen uebergeben")
        exitProcess(1)
    }
    println("Hallo, ${args[0]}!")
}

Zusammenfassung

  • Top-Level fun main() ist der Einstiegspunkt
  • $name / ${ausdruck} fuer String-Templates
  • readLine() liefert String? - mit ?: absichern
  • Ein-Ausdruck-Funktionen mit = statt { return ... }
  • when { ... } als ausdrucksstarke if/else-Kette
  • data class generiert toString, equals, copy etc.

Im naechsten Kapitel: Variablen, Typen und Kotlins Null-Safety im Detail.

Zurรผck zum Kotlin Kurs