在finally块中使用变量

2 scala

这是Scala中的代码:

def write() = {
    try {
      val out = new PrintWriter(new BufferedWriter(new FileWriter(fileName, true)))
      out.println("123")
      out.close
    } catch {
      case e: IOException => {}
    }

   //finally {
     //out.close // ops, it's not visible in this context
   //}
  }
Run Code Online (Sandbox Code Playgroud)

out.closefinally块中有" " 会更好,不是吗?但我不想使用var.

我的问题是,我该如何实现这一目标?

Rüd*_*ehn 9

块中定义的变量是该块的本地变量.因此,如果您坚持手动使用try/finally,则必须将val移出块.

但是,您要实现的是创建资源,在块中使用它,并在离开块时调用它的close方法,无论您是通过异常正常还是异常地离开块.这是一个非常常见的问题,因此已经有了一个库,称为Scala ARM.ARM代表自动资源管理.

这是基本用法:

import resource._
for(input <- managed(new FileInputStream("test.txt")) {
  // Code that uses the input as a FileInputStream
}
Run Code Online (Sandbox Code Playgroud)

有一些关于将此构造移动到scala标准库的讨论,因此将来您可能甚至不需要外部依赖.

我建议使用类似这样的库.它只是build.sbt中的一行.但是出于教育目的,这里是你自己的方式:

def managed[T <: AutoCloseable](resource:T) = new Traversable[T] {
  def foreach[U](f:T=>U) {
    try {
      f(resource)
    } finally {
      resource.close()
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

以下是如何使用它

scala> for(reader<-managed(new java.io.FileReader("/etc/passwd"))) { println(reader.read()) }
114

scala> for(reader<-managed(new java.io.FileReader("/etc/shadow"))) { println(reader.read()) }
java.io.FileNotFoundException: /etc/shadow (Permission denied)
...
Run Code Online (Sandbox Code Playgroud)

您仍将获得异常,但将调用close.当然,如果close也会引发异常,那么这将隐藏原始异常.像这样的小细节可能在scala ARM中处理得更好.