使用
use
API 來關閉已完成使用的資源。
在我們使用的資源中,有些資源在使用完成後不會自動停止使用狀態。因此,我們必須透過
close
等方法將這些資源的狀態更改為未使用。
Kotlin/JVM 所使用的 Java 標準函式庫中包含了許多這類資源。以下是代表性的資源,它們不會自動歸還:
- InputStream and OutputStream
- Java.sql.Connection
- Java.io.Reader ( FileReader, BufferedReader, CSSParser )
- Java.new.Socket and java.util.Scanner
所有對應的資源都支援繼承自
AutoCloseable
的
Closeable
介面。
請檢查以下語法。
fun countCharactersInFile(path:String):Int{
val reader = BufferedReader(FileReader(path))
try {
return reader.lineSequence().sumBy { it.length }
}
finally {
reader.close()
}
}
上述語法既複雜又不正確。因為如果在
finally
區塊中
reader.close()
發生錯誤,則無法處理。如果考慮到這點,我認為可以改成如下:
fun countCharactersInFile(path:String):Int{
val reader = BufferedReader(FileReader(path))
try {
return reader.lineSequence().sumBy { it.length }
}
finally {
try { reader.close() } catch (e: Exception) {}
}
}
這樣的實作雖然冗長且複雜,但因為很常見,所以標準函式庫將其提取為
use
函式。Kotlin 1.2 版本以上支援此功能。
以下提供除了書中範例之外,可供參考的範例。
try {
Socket("open", 80).use { socket ->
socket.getInputStream().use { inputStream ->
InputStreamReader(inputStream).use { reader ->
println(reader.readLines())
}
}
}
} catch (e: Exception) {
// ...
}
使用
use
時,如果進行巢狀使用,直接使用
it
可能會產生問題,因此建議根據作用域(Scope)進行宣告使用。
try with resources
我們習慣用 try-catch 來處理資源,但程式碼有時會變得複雜且雜亂。為了解決這個問題,提供了 try-with-resources 功能。簡單來說,它會在
try
區塊結束時,自動對在
try
中使用的資源執行
close
處理。
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();
}
}