在 Groovy(/Java) 中,抛出异常时如何从 stackTrace 中删除当前函数?

In Groovy(/Java) how would I remove the current function from the stackTrace when throwing an Exception?

我想提供一个抛出异常的函数,而不是直接抛出它们。例如。而不是写:

def foo() {
    def result = command_result("foo");
    if (!result) {
        throw new Exception("Bla!");
    }
    return result;
}

我想写这个:

def foo() {
    return command_result("foo") ?: error("Bla!");
}

需要定义函数error():

def error(msg) {
    throw new Exception(msg);
}

当然,我现在在调用堆栈顶部有 error(),所以如果我写

try {
    print(foo());
} catch(Exception error) {
    print("ERROR: ${error.stackTrace.head()}: ${error}");
}

我会得到类似

的东西
ERROR: Script1.error(Script1.groovy:19): java.lang.Exception: Bla!

为了摆脱堆栈上的 error:19 我想我可以只提取 error.stackTrace 上的第二项,但那会迫使我有一个通用的 try/catch 块。

是否有可能在 Groovy 中提供这样的功能(我猜它在 Java 中是一样的)即(重新)抛出一个异常,当前函数从后台跟踪中删除?

使用 getStackTrace,然后删除您不想出现的项目,然后使用 setStracTrace 进行异常更改。

https://docs.oracle.com/javase/7/docs/api/java/lang/Throwable.html#setStackTrace(java.lang.StackTraceElement[])

在 groovy 中很难删除属于最新调用的所有堆栈跟踪元素。但是,您可以在执行此操作之前清理堆栈跟踪(删除所有 groovy 内部项目):

def error(msg) {
  def e = new Exception(msg)
  e = org.codehaus.groovy.runtime.StackTraceUtils.sanitize(e)
  //drop items with unknown source and drop first element of stacktrace
  e.setStackTrace( e.getStackTrace().findAll{ it.getFileName() }.drop(1) as StackTraceElement[] )
  throw e
}

def foo(x) {
    return x ?: error("Bla!")
}

try{
  foo(0)
}catch(e){
  assert e.stackTrace[0].methodName=='foo'
  e.printStackTrace()
}

注意: 如果您 运行 groovyconsole 中的此代码,必须禁用 View / Show Full Stack Trace 菜单项以使 sanitize工作