我想创建一个尝试调用主函数的函数。如果可以,则将该函数的结果返回到外部。但如果失败 - 调用另一个函数(后备函数)并将其结果返回到外部。如果两者都失败 - 应传播第二个函数的异常。
我已经创建了打赏功能:
fun<T> callWithFallback(
main: () -> T,
fallback: () -> T
): T = try {
main()
} catch (e: Exception) {
logger.warn(e) { "main call failed: ${e.message}" }
if (/*some condition*/) {
try {
fallback()
} catch (e: LDAPException) {
logger.warn(e) { "Repeated call failed: ${e.message}" }
throw e
}
}
throw e
}
如果 main 失败 -
fallback()
被调用,但即使成功 - 也会抛出异常(最后一个 throw e
被调用)
我尝试添加
return
fun<T> callWithFallback(
main: () -> T,
fallback: () -> T
): T = try {
main()
} catch (e: Exception) {
logger.warn(e) { "main call failed: ${e.message}" }
if (/*some condition*/) {
try {
return fallback()
} catch (e: LDAPException) {
logger.warn(e) { "Repeated call failed: ${e.message}" }
throw e
}
}
throw e
}
但是会导致编译错误。
我该如何修复它?
您当前实现的问题来自第一个
if
子句中没有 else
的 catch
语句:
要了解从 catch 中返回什么,Kotlin 编译器会查看它包含的最后一条语句。在这里,它是
throw e
,而不是包含所需后备的 if。
由于您的
if
没有 else
分支,因此它被视为 语句而不是表达式。因此,它无法返回任何内容。您可以通过从 throw e
子句中删除 catch
来测试此断言。然后,编译器将发出警告,解释它无法从 catch
子句返回任何内容:
如果用作表达式,'if' 必须同时具有主分支和 'else' 分支
要解决您的问题,您可以将函数底部的
throw e
语句移至 else 子句中,如下所示:
fun<T> callWithFallback(
main: () -> T,
fallback: () -> T
): T = try {
main()
} catch (e: Exception) {
logger.warn(e) { "main call failed: ${e.message}" }
if (/*some condition*/) {
try {
return fallback()
} catch (e: LDAPException) {
logger.warn(e) { "Repeated call failed: ${e.message}" }
throw e
}
} else {
throw e
}
}
这样做会使
if/else
成为 catch
子句中的最新语句,并且由于它是一个表达式(由于 else 分支的存在),因此其结果被视为 catch 的返回值。