2012-09-11 7 views
5

Ich versuche, Mutables Variablen zu vermeiden, aber das Problem ist, dass ich auf ein val zugreifen muss, dass ich innerhalb der versuchen muss initialisieren (es ist eine db-Operation, die fehlschlagen mig) und ich brauche, dass var in dem finally-Blockscala: wie man Mutables in try catch Blöcke zu vermeiden

ich habe versucht, mit mehreren Alternativen:

erklären die val innerhalb des try-Blockes

try { 
    val resultSet = SQL(sql).resultSet 
    return ColumnInfo(resultSet.getMetaData) 
} catch { 
    case e => throw new ColumnInfoException("Error getting metadata") 
} finally { 
    resultSet.close 
} 

error: not found: value resultSet 

die val außerhalb des try-Blockes deklariert ohne Initialisierung es

val resultSet: java.sql.ResultSet 
try { 
    resultSet = SQL(sql).resultSet 
    return ColumnInfo(resultSet.getMetaData) 
} catch { 
    case e => throw new ColumnInfoException("Error getting metadata") 
} finally { 
    resultSet.close 
} 

error: only classes can have declared but undefined members 

eine var, die

var resultSet: java.sql.ResultSet = null 
try { 
    resultSet = SQL(sql).resultSet 
    return ColumnInfo(resultSet.getMetaData) 
} catch { 
    case e => throw new ColumnInfoException("Error getting metadata") 
} finally { 
    resultSet.close 
} 

und schließlich Verschachtelung try-catch-Block scheint zu funktionieren, die

try { 
    val resultSet = SQL(sql).resultSet 
    try { 
    return ColumnInfo(resultSet.getMetaData) 
    } catch { 
    case e => throw new ColumnInfoException("Error getting metadata") 
    } finally { 
    resultSet.close 
    } 
} catch { 
    case e => throw new ColumnInfoException("Error opening resultSet") 
} 

Gibt es einen besseren Ansatz, den ich nehmen zu vermeiden, eher schmutzig scheint Verwenden von Vars und Schachteln Try-Catch-Blöcke?

Antwort

0

des ersten catch-Block Befreien Sie:

try { 
    val resultSet = SQL(sql).resultSet 
    try { 
    ColumnInfo(resultSet.getMetaData) 
    } finally { 
    resultSet.close 
    } 
} catch { 
    case e => throw new ColumnInfoException("Error opening resultSet") 
} 
+0

Auswerten, um die down vote zu erklären? – nilskp

+0

der zweite Fang würde auch jede Ausnahme vom ersten Versuch fangen, oder? (upvoted, weil es meine eigene Version verbessert ...) – opensas

+0

Ja, es wird die Ergebnismenge schließen, aber den Fang an den äußeren try Block zurücklassen. – nilskp

3
import scala.util.control.Exception._ 

allCatch.either(SQL(sql).resultSet).right.flatMap{ resultSet => 
    val ans = allCatch.either(ColumnInfo(resultSet.getMetaData)) 
    resultSet.close 
    ans 
}.fold(e => throw e, identity) 

oder Sie können die fold überspringen und die Ausnahme (en) in Left verpackt halten.

1

In Scala, try Block ist an expression. In Ihrem Fall kann es zu einem Tupel, das beide val s enthält:

val res: (java.sql.ResultSet, ColumnInfo) = try { 
    val rs = SQL(sql).resultSet 
    (rs, ColumnInfo(rs.getMetaData)) 
} catch { 
    case _: Throwable => throw new Exception("Error getting metadata") 
} finally { 
    res._1.close 
} 
val columnInfo = res._2