scala 从 try-catch 返回一个值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17500955/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Returning a value from try-catch
提问by Alan Coromano
Here is a method in Scala:
这是 Scala 中的一个方法:
def method1(arg: String*): List[String] = {
try {
new MyClass(new URL(arg(0)))
.map(x => x.getRawString.toString)
}
catch {
case e: Exception => e.printStackTrace()
}
}
It complains on
它抱怨
found : Unit
[error] required: List[String]
If I added an additional value so that:
如果我添加了一个附加值,以便:
def method1(arg: String*): List[String] = {
val result = try {
new MyClass(new URL(arg(0)))
.map(x => x.getRawString.toString)
}
catch {
case e: Exception => e.printStackTrace()
}
result
}
it would say
它会说
found : Any
[error] required: List[String]
which is odd -- isn't this the same as the first approach?
这很奇怪——这与第一种方法不一样吗?
Anyway, what is the Scala's standard way of dealing with this kind of situations -- returning a value from try { .. } catch { .. }?
无论如何,Scala 处理这种情况的标准方法是什么——从 返回一个值try { .. } catch { .. }?
回答by Petr Pudlák
The problem is that in the case of an exception, there is no value to return. So you have to decide what value to return in such a case. It can be an empty list (if you really don't care about handling the error - not recommended!):
问题是在出现异常的情况下,没有返回值。所以你必须决定在这种情况下返回什么值。它可以是一个空列表(如果你真的不关心处理错误 - 不推荐!):
def method1(arg: String*): List[String] =
try {
new MyClass(new URL(arg(0)))
.map(x => x.getRawString.toString)
} catch {
case e: Exception => { e.printStackTrace(); Nil; }
}
A standard Scala way would be to return an Option, which makes it clear to the caller what happened:
标准的 Scala 方法是返回一个Option,这让调用者清楚发生了什么:
def method1(arg: String*): Option[List[String]] =
try {
Some(new MyClass(new URL(arg(0)))
.map(x => x.getRawString.toString))
} catch {
case e: Exception => { e.printStackTrace(); None; }
}
or perhaps return the exception itself:
或者可能返回异常本身:
def method1(arg: String*): Either[Exception,List[String]] =
try {
Right(new MyClass(new URL(arg(0)))
.map(x => x.getRawString.toString))
} catch {
case e: Exception => Left(e)
}
Since this pattern is relativelly common, there is a special Scala class Tryjust for this purpose, that gives these concepts meaningful names and adds many helpful methods. Try[A]encapsulates the result of a computation that returns A, or an exception if the computation failed:
由于这种模式相对常见,因此有一个专门Try用于此目的的特殊 Scala 类,它为这些概念提供了有意义的名称并添加了许多有用的方法。Try[A]封装返回的计算结果,A如果计算失败则封装异常:
sealed abstract class Try[+T]
final case class Success[+T](value: T) extends Try[T]
final case class Failure[+T](exception: Throwable) extends Try[T]
so a literal rewrite of your method would be
所以你的方法的字面重写将是
def method1(arg: String*): Try[List[String]] =
try {
Success(new MyClass(new URL(arg(0)))
.map(x => x.getRawString.toString))
} catch {
case e: Exception => Failure(e)
}
But of course Scala has methods for this pattern (after all that's what Tryis for), so you can write just
但是当然 Scala 有这个模式的方法(毕竟这就是Try它的目的),所以你可以只写
def method1(arg: String*): Try[List[String]] =
Try { new MyClass(new URL(arg(0)))
.map(x => x.getRawString.toString)) }
(There is a slight difference, Try { ... }also catches some Errors).
(有细微的差别,Try { ... }也抓到了一些Errors)。
回答by om-nom-nom
It complains because not all branches return the result:
它抱怨是因为并非所有分支都返回结果:
def method1(arg: String*): List[String] = {
try {
new MyClass(new URL(arg(0)))
.map(x => x.getRawString.toString) // ok, here I know what to do
}
catch {
case e: Exception => e.printStackTrace() // ???? What to return here???
// ok, will return Unit
}
}
The common type of Something and Unit is Any. So what you need to do in both cases (with, or without result variable) is to return value in both branches (possibly some dummy value, like empty List in catch case).
Some 和 Unit 的常见类型是 Any。所以在这两种情况下(有或没有结果变量)你需要做的是在两个分支中返回值(可能是一些虚拟值,比如 catch 情况下的空列表)。
EDIT
编辑
The errors are different because without val compiler can track that flow down to the branch and notice that function return type and catch result are different. With val there was no type constraints on val so it can happily inferthat val resulthas Any type and then, when you return result it confronts with function result type. If you specify result type explicitly as val result: List[String] = ...error message will be the same.
错误是不同的,因为没有 val 编译器可以跟踪到分支的流并注意到函数返回类型和捕获结果是不同的。随着VAL没有就没有VAL类型约束,因此它可以愉快地推断说val result有什么类型,然后,当你回来时导致其与功能的结果类型面对。如果您明确指定结果类型,则val result: List[String] = ...错误消息将相同。
回答by 4lex1v
In Scala such things should be better done with monadic style:
在 Scala 中,使用 monadic 风格应该更好地完成这些事情:
def fun(arg: Strign*): Option[List[String]] = Try {
new MyClass(new URL(arg(0))).map(_.getRawString.toString)
}.toOption
Update
更新
If you look at the implementation of Try's apply you'll see and interesting code:
如果您查看 Try 的 apply 的实现,您会看到有趣的代码:
/** Constructs a `Try` using the by-name parameter. This
* method will ensure any non-fatal exception is caught and a
* `Failure` object is returned.
*/
def apply[T](r: => T): Try[T] =
try Success(r) catch {
case NonFatal(e) => Failure(e)
}
so Try is just a wrapper for try/catch for monadic chaining
所以 Try 只是一个用于 monadic 链接的 try/catch 的包装器
回答by db killer
You could pass "null" as return type for most of the objects and String Types(which are subtypes of AnyRef). For example please see below
您可以将“null”作为大多数对象和字符串类型(它们是 AnyRef 的子类型)的返回类型传递。例如,请参见下文
def execute_rs(sql:String): ResultSet = {
try {
println("SQL IS " + sql)
val con = DriverManager.getConnection(url, username, password)
// println("statemetn created1")
val stmt = con.createStatement()
//println("statemetn created")
//str.foreach( i =>statement.addBatch(i))
val rs = stmt.executeQuery(sql)
return rs
}
catch {
case e: SQLException=> {println("exception occured in oracle sql insertion"+e); null}
case e: Exception=> {println("Common exception occured:"+e);null}
case _:Throwable => {println("some other exception occured");null}
}

