web-dev-qa-db-fra.com

Ressources d'essayage à Kotlin

Lorsque j'ai essayé d'écrire un équivalent d'un code Java try avec ressources, dans Kotlin, cela ne fonctionnait pas pour moi.

J'ai essayé différentes variantes de ce qui suit:

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

Mais ni fonctionne.

Est-ce que quelqu'un sait ce qui devrait être utilisé à la place? Apparemment, la grammaire Kotlin n'a pas de définition pour une telle construction, mais peut-être qu'il me manque quelque chose. Il définit la grammaire du bloc try comme suit:

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

Il y a use- fonction dans kotlin stdlib ( src ).

Comment l'utiliser:

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

TL; DR

Pas de syntaxe spéciale, mais use function

Kotlin, contrairement à Java, n'a pas de syntaxe spéciale pour cela. Au lieu de cela, try-with-resources, est proposé comme fonction de bibliothèque standard use.

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

L'implémentation 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()
        }
    }
}

Cette fonction est définie comme une extension générique sur tous les Closeable? les types. Closeable est le interface de Java qui permet try-with-resources à partir de Java SE7 .
La fonction prend une fonction littérale block qui est exécutée dans un try. Comme avec try-with-resources en Java, le Closeable obtient fermé dans un finally.

De plus, les échecs à l'intérieur de block conduisent à close exécutions, où les exceptions possibles sont littéralement "supprimées" en les ignorant. This est différent de try-with-resources, car de telles exceptions peuvent être demandées dans la solution de Java .

Comment l'utiliser

L’extension use est disponible sur n’importe quel type de Closeable, à savoir les flux, les lecteurs, etc.

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

La partie entre accolades est ce qui devient block dans use (un lambda est passé comme argument ici). Une fois le blocage effectué, vous pouvez être sûr que FileInputStream a été fermé.

35
s1m0nw1

Edit: La réponse suivante est toujours valable pour Kotlin 1.0.x. Pour Kotlin 1.1, une bibliothèque standard prend en charge Java 8 pour prendre en charge le modèle de ressource pouvant être fermé).

Pour les autres classes qui ne prennent pas en charge la fonction "use", j'ai effectué les try-with-resources maison suivants:

package info.macias.kotlin

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

Ensuite, vous pouvez l'utiliser de la manière suivante:

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