Use the use API to close resources once finished
Among the resources we use, there are some that do not automatically switch their state to stopped after usage is complete. We must change their state to an unused status using methods like close.
Standard Java libraries used in Kotlin/JVM contain many such resources. Notably, the following resources do not automatically return themselves:
- InputStream and OutputStream
- Java.sql.Connection
- Java.io.Reader ( FileReader, BufferedReader, CSSParser )
- Java.new.Socket and java.util.Scanner
All corresponding resources support the Closeable interface, which inherits from AutoCloseable.
Consider the following syntax:
fun countCharactersInFile(path:String):Int{
val reader = BufferedReader(FileReader(path))
try {
return reader.lineSequence().sumBy { it.length }
}
finally {
reader.close()
}
}
The syntax above is complex and incorrect because it cannot handle cases where reader.close() throws an error within the finally block. If we were to handle this, I think it could be changed as follows:
fun countCharactersInFile(path:String):Int{
val reader = BufferedReader(FileReader(path))
try {
return reader.lineSequence().sumBy { it.length }
}
finally {
try { reader.close() } catch (e: Exception) {}
}
}
While this implementation is long and complex, it is quite common, so it has been extracted into the standard library function use. This has been supported since Kotlin version 1.2.
I have provided an example to reference, along with the example found in the book.
try {
Socket("open", 80).use { socket ->
socket.getInputStream().use { inputStream ->
InputStreamReader(inputStream).use { reader ->
println(reader.readLines())
}
}
}
} catch (e: Exception) {
// ...
}
When using use, nesting it might cause issues if using it, so it is recommended to declare and use the variable according to its scope.
try with resources
Handling resources with a familiar try-catch can sometimes make code complex and messy. For this purpose, the try-with-resources feature is supported. In short, it automatically closes the resources used in the try block when the block finishes.
public static String getHtml(String url) throws IOException {
val targetUrl = URL(url);
try (val inputSR = new InputStreamReader(targetUrl.openStream());val bufferReader = BufferedReader(inputSR)){
val html = StringBuffer();
var tmp;
while ((tmp = reader.readLine()) != null) {
html.append(tmp);
}
return html.toString();
}
}