Coba-dengan-sumber daya di Kotlin

147

Ketika saya mencoba untuk menulis setara trydengan kode Java -dengan-sumber daya di Kotlin, itu tidak berhasil untuk saya.

Saya mencoba berbagai variasi berikut ini:

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

Tapi tidak ada yang berhasil.

Apakah ada yang tahu apa yang harus digunakan? Tampaknya tata bahasa Kotlin tidak memiliki definisi untuk konstruksi seperti itu, tapi mungkin aku kehilangan sesuatu. Ini mendefinisikan tata bahasa untuk blok coba sebagai berikut:

try : "try" block catchBlock* finallyBlock?;
Alex
sumber

Jawaban:

219

Ada use-fungsi di kotlin stdlib ( src ).

Bagaimana cara menggunakannya:

OutputStreamWriter(r.getOutputStream()).use {
    // by `it` value you can get your OutputStreamWriter
    it.write('a')
}
pengguna2235698
sumber
3
Saya sangat menyukai metode penyuluhan. Begitu banyak hal yang dapat Anda lakukan dan tidak perlu fitur bahasa tambahan.
Kirill Rakhman
20
Menambah ini, sebenarnya ada properti ekstensi untuk mendapatkan OutputStreamWriterjuga:r.outputStream.writer.use { ... }
Damian Wieczorek
3
Tautan ke dokumen rujukan yang menunjukkan useekstensi: kotlinlang.org/docs/reference/…
Javaru
1
Bagaimana saya bisa menggunakan multi "gunakan" dengan cara yang lebih baik? FileOutputStream(into).use { val mergingStream = BufferedOutputStream(it).use { } }
Ponomarenko Oleh
43

TL; DR: Tidak ada sintaks khusus, hanya sebuah fungsi

Kotlin, tidak seperti Java, tidak memiliki sintaks khusus untuk ini. Sebaliknya, coba-dengan-sumber daya , ditawarkan sebagai fungsi perpustakaan standar use.

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

The useimplementasi

@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()
        }
    }
}

Fungsi ini didefinisikan sebagai ekstensi umum pada semua Closeable?jenis. Closeableadalah antarmuka Java yang memungkinkan coba-dengan-sumber daya pada Java SE7 .
Fungsi ini mengambil fungsi literal blockyang dijalankan di a try. Sama seperti dengan coba-dengan-sumber daya di Jawa, Closeableakan ditutup dalam a finally.

Juga kegagalan yang terjadi di dalam blockmenyebabkan closeeksekusi, di mana kemungkinan pengecualian secara harfiah "ditekan" dengan hanya mengabaikannya. Ini berbeda dari coba-dengan-sumber daya , karena pengecualian seperti itu dapat diminta dalam solusi Java .

Bagaimana cara menggunakannya

The useekstensi tersedia pada setiap Closeablejenis, yaitu sungai, pembaca dan sebagainya.

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

Bagian dalam kurung keriting adalah apa yang menjadi blockdalam use(lambda dilewatkan sebagai argumen di sini). Setelah blok selesai, Anda dapat yakin bahwa FileInputStreamitu telah ditutup.

s1m0nw1
sumber
16

Sunting : Respons berikut masih valid untuk Kotlin 1.0.x. Untuk Kotlin 1.1, ada dukungan perpustakaan standar yang menargetkan Java 8 untuk mendukung pola sumber daya yang dapat ditutup.

Untuk kelas-kelas lain yang tidak mendukung fungsi "use", saya telah melakukan try-with-resources buatan sendiri berikut ini:

package info.macias.kotlin

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

Maka Anda dapat menggunakannya dengan cara berikut:

fun countEvents(sc: EventSearchCriteria?): Long {
    return trywr(connection.prepareStatement("SELECT COUNT(*) FROM event")) {
        var rs = it.executeQuery()
        rs.next()
        rs.getLong(1)
    }
}
Mario
sumber
1
Ini tidak berurusan dengan benar dengan pengecualian yang dikeluarkan dari klausa terakhir, yang merupakan salah satu alasan coba-dengan-sumber daya ditambahkan ke Jawa. Ini hanya try/finallyblok sederhana
Nikola Mihajlović
0

Karena posting StackOverflow ini berada di dekat bagian atas hasil pencarian saat ini untuk "contoh dekat kotlin," namun tidak ada jawaban lain (atau dokumen resmi) yang dengan jelas menjelaskan cara memperluas Closeable(alias java.io.Closeable), saya pikir saya akan menambahkan contoh tentang cara membuat kelas Anda sendiri yang meluas Closeable. Bunyinya seperti ini:

import java.io.Closeable

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

Dan kemudian menggunakannya:

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

Lihat contoh ini di Taman Bermain Kotlin sini .

Quuxplusone
sumber