9

我在文件中有以下虚拟 Scala 代码test.scala

class Transaction {
  def begin() {}
  def commit() {}
  def rollback() {}
}

object Test extends Application {
  def doSomething() {}

  val t = new Transaction()
  t.begin()
  try {
    doSomething()
    t.commit()
  } catch {
    case _ => t.rollback()
  }
}

如果我在 Scala 2.8 RC1 上编译它,scalac -Xstrict-warnings test.scala我会收到以下警告:

test.scala:16: warning: catch clause swallows everything: not advised.
    case _ => t.rollback()
    ^
one warning found

那么,如果不建议使用包罗万象的表达式,我应该如何实现这样的模式呢?除此之外,为什么不建议这种表达方式?

4

4 回答 4

9

存在警告是因为您可能不想捕获所有内容。例如,通常不建议尝试抓住任何东西,java.lang.Error因为通常很难从这些东西中恢复过来。(很有可能你会因为另一个例外而被赶出你的 catch 块。)

此外,由于您无法有效地捕获所有内容,因此这不是实现原子/故障安全事务的安全方法。你最好用类似的东西

try {
  t.commit()
} finally {
  if (!t.checkCommitted()) {
    t.rollback()
    if (!t.checkRolledback()) throw new FUBARed(t)
  }
}

在阅读新书时进行额外测试,t以确保它处于合理状态。

于 2010-04-28T06:25:19.380 回答
2

我没有编译器来测试这个,但你不应该在回滚事务后重新抛出异常吗?即这应该是

val t = new Transaction()
t.begin()
try {
  doSomething()
  t.commit()
} catch {
  case e => t.rollback(); throw e
}

如果您要捕获所有异常,则应注意. ControlThrowable大概您希望您的事务在异常终止时回滚,但不希望它为非本地返回或util.control.Breaks.break. 如果是这样,您可能想要执行以下操作:

val t = new Transaction()
t.begin()
try {
  doSomething()
  t.commit()
} catch {
  case ce : ControlThrowable => throw ce // propagate
  case e => t.rollback(); throw e        // roll-back and propagate
}
于 2010-04-28T06:17:53.917 回答
1

首先,请注意这是一个警告,而不是错误。即便如此,只有使用 -Xstrict-warings 选项才会发出警告。换句话说,这意味着你可能犯了一个逻辑错误,但这取决于你自己的决定。

正如其他人所注意到的,在大多数情况下,捕获所有异常是没有意义的,你应该这样做:

t.begin()
try {
  doSomething()
  t.commit()
} catch {
  case e: DuplicatedKeyError => ...
  case e: BrokenConnectionError => ...
  case e: DumbInputDetectedError => ...
}

即有意义地处理所有已知的错误类型。

但是,如果您确定要忽略(或以相同方式处理)所有可能的异常,则只需忽略警告。

于 2010-04-28T13:45:40.973 回答
1

你必须 catchThrowable来说明你想要捕捉所有东西的意图:

  try {
     android.util.Log.i (TAG, "Feature " + Text)
     statements
  }
  catch {
     case exception: Throwable =>
        val Message = "Feature " + Text + "failed"
        android.util.Log.e (TAG, Message, exception)
        fail (Message)
  } // try

上面的例子如果来自一个单元测试。正如警告所说:在正常代码中不建议使用

于 2014-03-20T15:00:37.793 回答