Probieren Sie Ressourcen in Kotlin aus

1. Einleitung

Verwaltete Sprachen, z. B. solche, die auf die JVM abzielen, verarbeiten automatisch die häufigste Ressource: Speicher.

Wir müssen uns jedoch mit allen Arten von Ressourcen befassen, nicht nur mit Speicher: Dateien, Netzwerkverbindungen, Streams, Fenstern usw. Und genau wie Speicher müssen diese freigegeben werden, wenn sie nicht mehr benötigt werden.

In diesem Artikel werden wir untersuchen, wie Ressourcen in Kotlin automatisch verwaltet werden können und wie sie sich vom Java-Konstrukt "Try-with-Resources" unterscheiden.

Wenn Sie die Theorie überspringen möchten, springen Sie direkt zum Beispiel.

2. Automatische Ressourcenverwaltung

Bei der Arbeit mit Ressourcen in Java (Pseudocode) können drei verschiedene Phasen unterschieden werden:

resource = acquireResource() try { useResource(resource) } finally { releaseResource(resource) } 

Wenn die Sprache oder Bibliothek für die Freigabe der Ressource verantwortlich ist (der letzte Teil), nennen wir dies automatische Ressourcenverwaltung. Diese Funktion entlastet uns von der Notwendigkeit, eine Ressource freizugeben.

Da die Ressourcenverwaltung normalerweise an einen Blockbereich gebunden ist, werden sie immer in der richtigen Reihenfolge freigegeben, wenn mehr als eine Ressource gleichzeitig bearbeitet wird.

In Java implementieren Objekte, die eine Ressource enthalten und für die automatische Ressourcenverwaltung geeignet sind, eine bestimmte Schnittstelle: Schließbar für E / A-bezogene Ressourcen und AutoCloseable .

Außerdem hat Java 7 die bereits vorhandene Closeable- Schnittstelle nachgerüstet , um AutoCloseable zu erweitern .

Daher hat Kotlin das gleiche Konzept von Ressourceninhabern: dh Objekte, die entweder Closeable oder AutoCloseable implementieren .

3. Die Use- Funktion in Kotlin

Um Ressourcen automatisch zu verwalten, verfügen einige Sprachen über ein dediziertes Konstrukt: Java 7 hat beispielsweise Try-with-Resources eingeführt, während C # das Schlüsselwort using verwendet .

Manchmal bieten sie uns ein Muster an, wie RAII in C ++. In einigen anderen Fällen geben sie uns eine Bibliotheksmethode.

Kotlin fällt in die letztere Kategorie.

Es gibt kein Sprachkonstrukt, das dem Versuch mit Ressourcen in Java ähnelt .

Stattdessen finden wir in der Standardbibliothek eine Erweiterungsmethode namens use .

Wir werden es uns später genauer ansehen. Im Moment müssen wir nur wissen, dass jedes Ressourceninhaberobjekt die Verwendungsmethode hat , die wir aufrufen können.

3.1. Wie man es benutzt

Ein einfaches Beispiel:

val writer = FileWriter("test.txt") writer.use { writer.write("something") }

Wir können die Verwendungsfunktion für jedes Objekt aufrufen , das AutoCloseable oder Closeable implementiert , genau wie beim Versuch mit Ressourcen in Java.

Die Methode nimmt einen Lambda-Ausdruck, führt ihn aus und verfügt über die Ressource (durch Aufrufen von close () ), wenn die Ausführung den Block entweder normal oder mit einer Ausnahme verlässt.

In diesem Fall kann der Writer nach der Verwendung nicht mehr verwendet werden, da Kotlin ihn automatisch geschlossen hat.

3.2. Eine kürzere Form

Im obigen Beispiel haben wir der Übersichtlichkeit halber eine Variable namens writer verwendet , um einen Abschluss zu erstellen.

Jedoch Verwendung akzeptiert ein Lambda - Ausdruck mit einem einzigen Parameter - das Objekt Halten der Ressource:

FileWriter("test.txt") .use { w -> w.write("something") }

Innerhalb des Blocks können wir auch die implizite Variable it verwenden :

FileWriter("test.txt") .use { it.write("something") }

Wie wir sehen können, müssen wir dem Objekt keinen expliziten Namen geben. In der Regel ist es jedoch eine gute Idee, klar zu sein, anstatt übermäßig präzisen Code zu schreiben.

3.3. Die Definition der Verwendung ()

Schauen wir uns die Definition der Verwendungsfunktion in Kotlin an, wie sie in der Standardbibliothek zu finden ist:

public inline fun  T.use(block: (T) -> R): R

Wir können sehen, in der Teilweise wird diese Verwendung als Erweiterungsfunktion auf der Closeable- Schnittstelle von Java definiert .

Weitere Informationen zu Erweiterungsmethoden finden Sie in unserem Einführungsartikel.

Natürlich ist die Verwendungsfunktion als Teil der Kotlin-Standardbibliothek dokumentiert.

3.4. Closeable vs AutoCloseable

Wenn wir das Beispiel aus dem vorherigen Abschnitt genauer betrachten, können wir sehen, dass die Signatur der Verwendungsfunktion nur auf der Closeable- Schnittstelle definiert ist. Dies liegt daran, dass die Standardbibliothek von Kotlin auf Java 6 abzielt.

In Java-Versionen vor 7 gab es AutoCloseable nicht und Closeable hat es natürlich nicht erweitert.

In der Praxis sind Klassen, die AutoCloseable, aber nicht Closeable implementieren , selten. Trotzdem können wir einem von ihnen begegnen.

In diesem Fall müssen wir nur eine Abhängigkeit von Kotlins Erweiterungen für Java 7, 8 oder eine andere Version hinzufügen, auf die wir abzielen:

 org.jetbrains.kotlin kotlin-stdlib-jdk8 

Die neueste Version der Abhängigkeit finden Sie in Maven Central.

Das gibt uns eine weitere Verwendung Erweiterungsfunktion auf der definierten AutoCloseable Schnittstelle:

public inline fun  T.use(block: (T) -> R): R

4. Fazit

In diesem Tutorial haben wir gesehen, wie eine einfache Erweiterungsfunktion in Kotlins Standardbibliothek alles ist, was wir benötigen, um alle Arten von Ressourcen, die der JVM bekannt sind, automatisch zu verwalten.

Die Implementierung all dieser Beispiele und Codefragmente finden Sie im GitHub-Projekt.