Kotlin-Updates: Kotlin 1.6

Seit einigen Tagen ist Kotlin 1.6 verfügbar. Dieser Beitrag geht auf die wichtigsten Neuerungen im Vergleich zu Version 1.5 ein. Die Kurzfassung: Kotlin 1.6 ist ein »kleines« Release, für die meisten Entwickler gibt es keine wirklich dramatische Änderungen. Auch die Verbesserungen in der Standardbibliothek sind eher Kleinigkeiten.

Dieser Text bezieht sich auf die folgenden Versionsnummern:

IntelliJ: 2021.2.3
Kotlin: 1.6.0
JDK: 17

Weitere Kotlin-Update-Artikel auf meiner Website finden Sie hier:

https://kofler.info/tag/kotlin-updates

Exhaustive »when«

In Kotlin 1.6 beklagt sich der Compiler, wenn eine when-Konstruktion für Enumerationen, boolesche Werte oder für Datentypen nicht alle möglichen Fälle erfasst, also nicht »exhaustive« ist. Aktuell können Sie diese Warnung noch ignorieren, aber in Kotlin 1.7 wird daraus ein Fehler. Spätestens dann müssen Sie die when-Konstruktion so formulieren, dass sämtliche Fälle erfasst werden (am einfachsten durch einen else-Block).

enum class Days {
    Monday, Tuesday, Wednesday, Thursday, 
    Friday, Saturday, Sunday
}

val day = Days.Friday
when(day) {
    Days.Monday, Days.Tuesday -> println("Wochenanfang")
    Days.Wednesday, Days.Thursday -> println("Wochenmitte")
    Days.Friday -> println("Fast geschafft")
    // Warnung:  Non exhaustive 'when' statements on enum will be prohibited 
    // in 1.7, add 'Saturday', 'Sunday' branches or 'else' branch instead
}

Standardbibliothek

readln: Wenn Sie mit readLine() eine Datei zeilenweise auslesen, liefert die Funktion entweder die nächste Zeile oder null. Nunmehr gibt es zwei Varianten zu readline, die die ursprüngliche Form längerfristig ablösen sollen:

  • readlnOrNull() verhält sich wie ehemals readLine(), ist aber klarer benannt und hat mehr Ähnlichkeiten mit println.

  • readln() löst dagegen einen Fehler aus, wenn das Ende der Datei erreicht ist, und kann statt dem wenig eleganten readLine()!! verwendet werden.

readLine() bleibt uns vorerst erhalten, soll aber in kommenden Kotlin-Versionen deprecated werden.

typeOf: typeOf<Typ> liefert ein KClass-Objekt, das Typ beschreibt. Die Funktion stand zwar schon seit Kotlin 1.3.40 zur Verfügung, ursprünglich aber nur für die JVM-Variante. Nunmehr kann typeOf in allen drei Kotlin-Varianten (also auch JS und Native) verwendet werden.

Duration-API: Die Duration API (beschrieben in Abschnitt 7.3 meines Kotlin-Buchs) gilt nun als stabil. Das gilt allerdings nicht für andere kotlin.time-Klassen zur Zeitmessung. Die in Kotlin 1.5 abgeschaffte Notation

val myDur = 2.minutes + 3.seconds - 10.milliseconds * 0.66

ist erfreulicherweise wieder eingeführt worden, erfordert nun aber Importe der betreffenden Companion-Eigenschaften, hier also:

import kotlin.time.Duration.Companion.minutes
import kotlin.time.Duration.Companion.seconds
import kotlin.time.Duration.Companion.milliseconds

Unsupported class file major version 61

Meine ersten Tests mit Kotlin scheiterten an Java 17. Auf meinem Rechner ist auch die JDK 17 installiert. Anscheinend ist das Build-System dazu nicht kompatibel. IntelliJ war nicht in der Lage, das minimalistische Console Template zu kompilieren und zeigte eine wenig hilfreiche Fehlermeldung an:

Could not open init generic class cache for initialization script '/tmp/wrapper_init4.gradle' (/crypt/home/kofler/.gradle/caches/7.1/scripts/954mesz5ux7usmane6uzpuni1).
> BUG! exception in phase 'semantic analysis' in source 
> unit '_BuildScript_' Unsupported class file major version 61

Eine kurze Suche in stackoverflow ergab, dass Kompatiblitätsprobleme zwischen Gradle und der JDK 17 die Ursache sein könnten. Ich habe dann die JDK-Version für das Build-System auf 11 zurückgesetzt, und alles funktionierte. Merkwürdig. (Es geht hier nicht um die JDK für das eigentliche Projekt, die darf sehr wohl 17 sein.)

Die von JVM eingesetzte JVM sollte nicht allzu aktuell sein …

Quellen/Links

Sonstiges: