Kotlinでのリソースの試用


147

tryKotlinでJava -with-resourcesコードに相当するコードを記述しようとしたところ、うまくいきませんでした。

次のさまざまなバリエーションを試しました。

try (writer = OutputStreamWriter(r.getOutputStream())) {
    // ...
}

しかしどちらも機能しません。

誰かが代わりに何を使うべきか知っていますか?どうやらKotlin文法にそのような構成の定義がありませんが、おそらく何かが足りません。これは、tryブロックの文法を次のように定義します。

try : "try" block catchBlock* finallyBlock?;

回答:


219

usekotlin stdlib(src)には-function があります。

どうやって使うのですか:

OutputStreamWriter(r.getOutputStream()).use {
    // by `it` value you can get your OutputStreamWriter
    it.write('a')
}

3
私は拡張メソッドが大好きです。多くのことができるので、追加の言語機能は必要ありません。
Kirill Rakhman、2014年

20
これに追加すると、実際に取得するために、拡張性がありOutputStreamWriter、ならびに:r.outputStream.writer.use { ... }
ダミアンWieczorek

3
実証リファレンスドキュメントへのリンクuse:拡張子をkotlinlang.org/docs/reference/...
Javaru

1
より良い方法でマルチ「使用」を使用するにはどうすればよいですか? FileOutputStream(into).use { val mergingStream = BufferedOutputStream(it).use { } }
Ponomarenko Oleh

43

TL; DR:特別な構文はなく、関数のみ

Javaとは対照的に、Kotlinにはこのための特別な構文はありません。代わりに、try-with-resourcesが標準ライブラリ関数として提供されていますuse

FileInputStream("filename").use { fis -> //or implicit `it`
   //use stream here
} 

use実装

@InlineOnly
public inline fun <T : Closeable?, R> T.use(block: (T) -> R): R {
    var closed = false
    try {
        return block(this)
    } catch (e: Exception) {
        closed = true
        try {
            this?.close()
        } catch (closeException: Exception) {
        }
        throw e
    } finally {
        if (!closed) {
            this?.close()
        }
    }
}

この関数は、すべてのCloseable?タイプの一般的な拡張として定義されています。Java SE7の時点でリソース試すことができるCloseableJavaのインターフェースです。 この関数、で実行される関数リテラルを取ります。同じのtry-と資源 Javaで、取得し閉じで。
blocktryCloseablefinally

また、内部で発生した障害は実行にblockつながりclose、可能な例外は無視するだけで文字通り「抑制」されます。このような例外はJavaのソリューションで要求できるため、これtry-with-resourcesとは異なります。

どうやって使うのですか

use拡張子は、任意の上で利用可能であるCloseable読者とそうで、すなわちストリーム、タイプ。

FileInputStream("filename").use {
   //use your stream by referring to `it` or explicitly give a name.
} 

中括弧で囲まれた部分が何になるかblockですuse(ここでは引数としてラムダが渡されます)。ブロックが完了したら、それがFileInputStream閉じられていることを確認できます。


16

編集:次の応答はKotlin 1.0.xでも有効です。Kotlin 1.1の場合、Java 8をターゲットとして、クローズ可能なリソースパターンをサポートする標準ライブラリがサポートされています。

「use」関数をサポートしない他のクラスについては、次の自家製のtry-with-resourcesを実行しました。

package info.macias.kotlin

inline fun <T:AutoCloseable,R> trywr(closeable: T, block: (T) -> R): R {
    try {
        return block(closeable);
    } finally {
        closeable.close()
    }
}

その後、次のように使用できます。

fun countEvents(sc: EventSearchCriteria?): Long {
    return trywr(connection.prepareStatement("SELECT COUNT(*) FROM event")) {
        var rs = it.executeQuery()
        rs.next()
        rs.getLong(1)
    }
}

1
これは、finally節からスローされた例外を適切に処理しません。これは、try-with-resourcesがJavaに追加された理由の1つです。これは単純なtry/finallyブロックです
NikolaMihajlović2018

0

このStackOverflowの投稿は、「kotlinクローズ可能な例」の現在の検索結果の上部にありますが、他の回答(または公式ドキュメント)はどれも拡張方法Closeable(別名java.io.Closeable)を明確に説明していないため、例を追加すると思います拡張する独自のクラスを作成する方法のCloseable。こんなふうになります:

import java.io.Closeable

class MyServer : Closeable {
    override fun close() {
        println("hello world")
    }
}

そしてそれを使うには:

fun main() {
    val s = MyServer()
    s.use {
        println("begin")
    }
    println("end")
}

こちらのKotlin Playgroundのこの例をご覧ください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.