我正在设计一个简单的玩具解释器,我有一个自定义异常,如下所示:
class ValError(varName: String) : Exception("$varName is val, cannot reassign.")
问题是,当它被抛出时,它打印出整个调用堆栈跟踪,如下所示:
ValError: foo is val, cannot reassign.
at com.github.me.dynamik.interpreter.Environment.get(Environment.kt:62)
at com.github.me.dynamik.interpreter.TreeWalker.visitVariableExpr(TreeWalker.kt:154)
at com.github.me.dynamik.expressions.VariableExpr.evaluateBy(Expression.kt:57)
但我只想打印出第一行
ValError: foo is val, cannot reassign.
我该如何做到这一点?
简短的回答:抓住异常,并打印其message字段。您可以在顶级函数中的try
... catch
块中执行此操作,或者(更好)在UncaughtExceptionHandler中执行此操作。
长期无聊的回答:
异常将从每个函数传递给它的调用者,直到找到一个带有封闭的try
... catch
块的异常。
所以一种方法是自己捕捉异常,例如:
fun main() {
try {
// All your top-level code here…
} catch (x: Exception) {
System.err.println(x.message)
}
}
如果您正在使用日志框架,那么您当然可以使用它。
如果没有封闭的try
... catch
,它将调用线程的UncaughtExceptionHandler - 或者,如果线程没有一个,它的ThreadGroup的一个,或者失败,the default one。
如果您没有提供默认值,系统会调用其printStackTrace()方法,该方法将异常消息及其所有回溯打印到标准错误流 - 这就是您看到问题中显示的跟踪的原因。
所以另一种方法是将UncaughtExceptionHandler设置为其中一个级别,例如:
Thread.setDefaultUncaughtExceptionHandler { t, x ->
System.err.println(x.message)
}
这样更安全,因为它适用于所有线程。
如果您正在编写一个仅使用单个线程的简单应用程序,那么可以直接在顶级方法中捕获异常。但是如果您正在编写使用GUI工具包或Web框架的东西,或者使用协同程序或其他执行框架,或者手动启动任何线程,那么可能会有其他线程在运行。这有两个影响:
因此,在记录异常之后,在某些情况下,处理程序关闭整个应用程序可能是一个非常好的主意。
(顺便说一句,第三种方法是使用自定义Exception
并覆盖其printStackTrace()
方法仅打印消息。但这不是一个好主意;它会破坏该方法的意图,这可能会导致任何使用的问题的各种问题它。)
使用try..catch
科特林
try {
// perform tasks
throw ValError("x")
} catch (e: ValError) {
println(e.message)
}
Java的
try{
// perform task
throw new ValError("x")
}
catch(ValError e){
System.out.println(e.getMessage());
}