Java用Groovy处理抛出异常的闭包

Wil*_*ood 8 java groovy exception

我们有一个可以使用groovy脚本进行自定义的系统,我发现这些脚本抛出的异常类型有一个非常奇怪的影响.

我们有一个groovy脚本,包含以下内容:

process {
   throw new Exception("weeee")
}
Run Code Online (Sandbox Code Playgroud)

进程被定义为脚本基类中的Closure:

public abstract class ScriptBaseClass extends Script {
   Closure process;

   public void process( Closure code ) {
      process = (Closure) code.clone();
   } 
}
Run Code Online (Sandbox Code Playgroud)

在实际运行脚本的Java类中,我们有以下方法(省略了所有设置代码,因为它似乎不相关):

public void process() {
   try {
      script.process.call();
   } catch (Exception e) {
      logger.debug("exception thrown from groovy script", e);
      throw e;
   }
}
Run Code Online (Sandbox Code Playgroud)

请注意,此处的处理方法不会声明它会抛出任何异常.然而,很明显它重新抛出了它捕获的异常e.这段代码是有效的,它编译和运行非常愉快.它按我的意愿抛出异常.

有谁知道这是合法代码?从理论上讲,我不应该从一个没有声明它抛出它的方法中抛出一个已检查的异常.

Igo*_*nov 8

它的工作原理是因为Java编译器(从Java 7开始)可以确定重新抛出的异常.因为catch (Exception e)它认为这是RuntimeException因为没有声明其他(已检查)异常call().

你可以在那里阅读它,例如:https://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html

所以这段代码完美编译:

public void xxxxx() {
    try {
        System.out.println('Hi!'); //or anything else w/o declared exceptions
    } catch (Exception e) {
        throw e;
    }
}
Run Code Online (Sandbox Code Playgroud)

Java编译看到只能在这里捕获RuntimeException,所以它不会要求你声明任何东西.

但为此:

public void xxxxx() {
    try {
        throw new IOException(); //or anything that have declared checked exception
    } catch (Exception e) {
        throw e;
    }
}
Run Code Online (Sandbox Code Playgroud)

它将无法编译,因为IOException可能被捕获并重新抛出