2010-04-28 17 views
9

Tengo el siguiente código Scala maniquí en el archivo test.scala:capturar todas las excepciones en Scala 2.8 RC1

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() 
    } 
} 

Si compilar esto en Scala 2.8 RC1 con scalac -Xstrict-warnings test.scala Voy a por el siguiente aviso:

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

Entonces, si no se recomiendan las expresiones catch-all, ¿cómo se supone que implemente un patrón así? Y aparte de eso, ¿por qué no se recomiendan tales expresiones de todos modos?

Respuesta

9

La advertencia existe porque probablemente no quiera ver todo. Por ejemplo, generalmente no es aconsejable tratar de detectar nada en java.lang.Error ya que a menudo es difícil recuperarse de tales cosas. (Es probable que salga despedido de su bloque catch con otra excepción).

Además, como no puede capturar todo, esta no es una forma segura de implementar transacciones atómicas/de seguridad. Es mejor que con algo como

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

con pruebas adicionales al leer en una nueva t para asegurarse de que está en un estado razonable.

+0

OK. Este funciona para transacciones. Pero, ¿qué sucede si quiero ignorar por completo una excepción arrojada por un método simplemente porque no importa en este momento? –

+5

Puedes 'atrapar {caso _: Excepción =>}'. 'Error' es' Throwable' pero no una 'Exception', por lo general es mejor pasar. Si realmente quiere decir: "No me importa si lo intento y no lo veo, al menos quiero dar lo mejor", entonces puede vivir con el mensaje de advertencia (estricto). Es por eso que es una advertencia, no un error. –

+0

Sí, eso funciona. ¡Gracias! Tienes razón, que atrapar 'Error' no es realmente lo que quiero :-) –

2

No tengo un compilador a mano para probar esto, pero ¿no debería volver a lanzar la excepción después de deshacer la transacción? es decir, esto debería ser

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

Si tienes que coger todas las excepciones, usted debe tomar nota de the documentation for ControlThrowable. Presumiblemente, desea que su transacción retroceda en la terminación anormal, pero no desea que se retrotraiga para una devolución no local o util.control.Breaks.break. Si es así, es posible que desee hacer algo como lo siguiente:

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 
} 
+0

Gracias, pero este código todavía conduce a la advertencia antes mencionada. –

+0

does 'case e => throw e' clear the callstack? –

1

Primero, observe que esto es una advertencia, no un error. Y aun así, una advertencia planteada solo con la opción -Xstrict-warings. En otras palabras, significa que tal vez está cometiendo un error de lógica, pero le corresponde a usted decidir.

Como otros han notado, en la mayoría de los casos no es significativa para atrapar toda excepción y que debe hacer algo como esto:

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

tipos de error es decir, mango meaningfuly todos conocidos.

Pero si está seguro de que desea ignorar (o manejar de la misma manera) todas las excepciones posibles, simplemente ignore la advertencia.

1

tienes que coger Throwable de indicar su intención de capturar todo:

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 

En el ejemplo anterior, si a partir de una pieza de prueba de unidad. Como dice la advertencia: no se recomienda en el código normal

Cuestiones relacionadas