1. 序章

JVMを対象とする言語などの管理対象言語は、最も一般的なリソースであるメモリを自動的に処理します。

ただし、メモリだけでなく、ファイル、ネットワーク接続、ストリーム、ウィンドウなど、あらゆる種類のリソースを処理する必要があります。 そして、メモリと同じように、それらは不要になったときに解放する必要があります。

この記事では、Kotlinでリソースを自動的に管理する方法と、Javaのtry-with-resourcesコンストラクトとの違いについて説明します。

理論をスキップしたい場合は、は例に直接ジャンプします。

2. 自動リソース管理

Java(擬似コード)でリソースを操作する場合、3つの異なるフェーズを区別できます。

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

言語またはライブラリがリソースの解放を担当している場合( 最後に一部)、それから私たちはそれを呼びます自動リソース管理。 そのような機能リソースを解放することを覚えておく必要がなくなります。

また、リソース管理は通常ブロックスコープに関連付けられているため、同時に複数のリソースを処理する場合、それらは常に正しい順序で解放されます。

Javaでは、リソースを保持し、自動リソース管理の対象となるオブジェクトは、特定のインターフェースを実装します。I/O関連リソースの場合はCloseable AutoCloseableです。

また、Java 7は、既存の Closeable インターフェースを改良して、AutoCloseableを拡張しました。

したがって、Kotlinには、リソースホルダーの同じ概念があります。つまり、CloseableまたはAutoCloseableのいずれかを実装するオブジェクトです。

3. Kotlinのuse関数

リソースを自動的に管理するために、一部の言語には専用の構造があります。たとえば、Java7ではtry-with-resources が導入され、C#ではusingキーワードが導入されました。

時々、C++RAIIのようなパターンを提供します。 他のいくつかのケースでは、それらは私たちにライブラリメソッドを提供します。

Kotlinは後者のカテゴリに分類されます。

設計上、 Javaのtry-with-resourcesに似た言語構造はありません。

代わりに、標準ライブラリでuseという拡張メソッドを見つけることができます。

これについては後で詳しく説明します。 今のところ、すべてのリソースホルダーオブジェクトには、呼び出すことができるuseメソッドがあることを知っておく必要があります。

3.1. それの使い方

簡単な例:

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

Javaのtry-with-resourcesの場合と同様に、AutoCloseableまたはCloseableを実装する任意のオブジェクトでuse関数を呼び出すことができます。

このメソッドはラムダ式を受け取り、それを実行し、通常または例外のいずれかで実行がブロックを離れるたびに( close()を呼び出すことによって)のリソースを破棄します。

したがって、この場合、の使用後、 ライターは、Kotlinによって自動的に閉じられたため、使用できなくなります。

3.2. 短い形式

上記の例では、わかりやすくするために、 writer という変数を使用して、クロージャを作成しました。

ただし、 use は、単一のパラメーターリソースを保持するオブジェクトを持つラムダ式を受け入れます。

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

ブロック内では、暗黙の変数itを使用することもできます。

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

したがって、ご覧のとおり、オブジェクトに明示的な名前を付ける必要はありません。 ただし、通常は、過度に簡潔なコードを記述するのではなく、明確にすることをお勧めします。

3.3. use()の定義

Kotlinのuse関数の定義を見てみましょう。これは、標準ライブラリにあります。

public inline fun <T : Closeable?, R> T.use(block: (T) -> R): R

私たちは、で見ることができます一部、それ使用は、JavaのCloseableインターフェースの拡張関数として定義されています。

拡張方法の詳細については、紹介記事を参照してください。

もちろん、使用機能はKotlinの標準ライブラリの一部として文書化されています

3.4. Closeable vs AutoCloseable

前のセクションの例に注意を払うと、use関数シグネチャがCloseableインターフェイスでのみ定義されていることがわかります。 これは、Kotlinの標準ライブラリがJava6を対象としているためです。

7より前のJavaバージョンでは、 AutoCloseable は存在しませんでした。もちろん、Closeableはそれを拡張しませんでした。

実際には、 AutoCloseable を実装しているが、Closeableを実装していないクラスはまれです。 それでも、そのうちの1つに遭遇する可能性があります。

その場合、Java 7、8、またはターゲットとするバージョンに対するKotlinの拡張機能への依存関係を追加するだけで済みます。

<dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-stdlib-jdk8</artifactId>
</dependency>

依存関係の最新バージョンは、 MavenCentralにあります。

これにより、AutoCloseableインターフェイスで定義された別のuse拡張関数が得られます。

public inline fun <T : AutoCloseable?, R> T.use(block: (T) -> R): R

4. 結論

このチュートリアルでは、Kotlinの標準ライブラリの単純な拡張関数が、JVMに認識されているすべての種類のリソースを自動的に管理するために必要なすべてのものであることを確認しました。

これらすべての例とコードスニペットの実装は、GitHubプロジェクトにあります。