使用 Groovy 处理抛出异常的闭包的 Java
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31984988/
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
Java with Groovy handling of closures throwing Exceptions
提问by Wil Selwood
We have a system that is possible to customise using groovy scripts and I've spotted a very strange effect on the type of exceptions throw from these scripts.
我们有一个可以使用 groovy 脚本进行自定义的系统,我发现对这些脚本抛出的异常类型产生了非常奇怪的影响。
We have a groovy script with the following:
我们有一个包含以下内容的 groovy 脚本:
process {
throw new Exception("weeee")
}
Process is defined as a Closure in the base class of the script:
Process 在脚本的基类中被定义为一个闭包:
public abstract class ScriptBaseClass extends Script {
Closure process;
public void process( Closure code ) {
process = (Closure) code.clone();
}
}
In the Java classthat actually runs the scripts we have the following method (omitted all the set up code as it doesn't seem relevant):
在实际运行脚本的Java 类中,我们有以下方法(省略了所有设置代码,因为它似乎不相关):
public void process() {
try {
script.process.call();
} catch (Exception e) {
logger.debug("exception thrown from groovy script", e);
throw e;
}
}
Note the process method here doesn't declare it throws any exceptions. However it quite clearly re-throws the Exception e that it caught. This code is valid, it compiles and runs quite happily. It throws the Exception as I wanted.
注意这里的 process 方法没有声明它抛出任何异常。然而,它很明显地重新抛出了它捕获的异常 e。这段代码是有效的,它编译并运行得非常愉快。它按照我的意愿抛出异常。
Does any one know how this is legal code? In theory I shouldn't be able to throw a checked exception out of a method that doesn't declare that it throws it.
有谁知道这是如何合法的代码?从理论上讲,我不应该从没有声明它抛出它的方法中抛出一个已检查的异常。
采纳答案by Igor Artamonov
It works because Java compiler (starting since Java 7) can determine re-thrown exception. For catch (Exception e)
it thinks it's RuntimeException
because there were no other (checked) exception declared in call()
.
它之所以有效是因为 Java 编译器(从 Java 7 开始)可以确定重新抛出的异常。因为catch (Exception e)
它认为这是RuntimeException
因为在call()
.
You can read about it there, for example: https://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html
您可以在那里阅读,例如:https: //docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html
So this code compiles perfectly:
所以这段代码可以完美编译:
public void xxxxx() {
try {
System.out.println('Hi!'); //or anything else w/o declared exceptions
} catch (Exception e) {
throw e;
}
}
Java compiled sees that only RuntimeException could be caught here, so it doesn't ask you do declare anything.
Java 编译看到这里只能捕获 RuntimeException,因此它不会要求您声明任何内容。
But for this:
但为此:
public void xxxxx() {
try {
throw new IOException(); //or anything that have declared checked exception
} catch (Exception e) {
throw e;
}
}
it will fail to compile, because IOException
could be caught and re-thrown
它将无法编译,因为IOException
可能会被捕获并重新抛出
回答by blackdrag
Groovy and the JVM don't really care about an exception being a checked one or not. Only the Java compiler cares about this here. In fact you can use the catch on any RuntimeException or its parent classes (of which Exception is one) without requiring it being declared as thrown from something called in the try-block. So it is fine by the compiler to catch Exception or Throwable even. Of course, from a program logic view it is an entirely different matter.
Groovy 和 JVM 并不真正关心异常是否被检查。这里只有 Java 编译器关心这个。事实上,您可以在任何 RuntimeException 或其父类(其中 Exception 是其中之一)上使用 catch ,而无需将其声明为从 try 块中调用的某个对象抛出。因此,编译器甚至可以捕获 Exception 或 Throwable 。当然,从程序逻辑的角度来看,这是完全不同的事情。
回答by Jeff Scott Brown
Introducing closures or anything Groovy related is unnecessary complexity. The following is valid Java code:
引入闭包或任何与 Groovy 相关的东西都是不必要的复杂性。以下是有效的 Java 代码:
public class Demo {
public void someMethod() {
try {
System.out.println("Hello");
} catch (Exception e) {
throw e;
}
}
}
Note that the following is not valid and will not compile:
请注意,以下内容无效且无法编译:
import java.sql.*;
public class Demo {
public void someMethod() {
try {
Connection c = DriverManager.getConnection("", "", "");
} catch (SQLException e) {
throw e;
}
}
}