是否有可能在Java中构造一段代码,使假设的Java .lang. chucknorrisexception无法捕获?
我想到的是使用拦截器或面向方面的编程。
是否有可能在Java中构造一段代码,使假设的Java .lang. chucknorrisexception无法捕获?
我想到的是使用拦截器或面向方面的编程。
当前回答
Two fundamental problems with exception handling in Java are that it uses the type of an exception to indicate whether action should be taken based upon it, and that anything which takes action based upon an exception (i.e. "catch"es it) is presumed to resolve the underlying condition. It would be useful to have a means by which an exception object could decide which handlers should execute, and whether the handlers that have executed so far have cleaned things up enough for the present method to satisfy its exit conditions. While this could be used to make "uncatchable" exceptions, two bigger uses would be to (1) make exceptions which will only be considered handled when they're caught by code that actually knows how to deal with them, and (2) allow for sensible handling of exceptions which occur in a finally block (if a FooException during a finally block during the unwinding of a BarException, both exceptions should propagate up the call stack; both should be catchable, but unwinding should continue until both have been caught). Unfortunately, I don't think there would be any way to make existing exception-handling code work that way without breaking things.
其他回答
抛出的任何异常都必须扩展Throwable,因此总是可以捕获它。所以答案是否定的。
如果你想让它难以处理,你可以重写方法getCause(), getMessage(), getStackTrace(), toString()抛出另一个java.lang.ChuckNorrisException。
不。Java中的所有异常都必须成为Java .lang的子类。虽然这可能不是一个好的实践,但你可以像这样捕获每种类型的异常:
try {
//Stuff
} catch ( Throwable T ){
//Doesn't matter what it was, I caught it.
}
有关更多信息,请参阅java.lang.Throwable文档。
如果您试图避免检查异常(必须显式处理的异常),那么您将希望继承Error或RuntimeException类。
我的答案是基于@jtahlborn的想法,但它是一个完全可用的Java程序,可以打包到JAR文件中,甚至可以作为web应用程序的一部分部署到您最喜欢的应用服务器上。
首先,让我们定义ChuckNorrisException类,这样它就不会从一开始就崩溃JVM(顺便说一句,Chuck真的很喜欢崩溃JVM:)
package chuck;
import java.io.PrintStream;
import java.io.PrintWriter;
public class ChuckNorrisException extends Exception {
public ChuckNorrisException() {
}
@Override
public Throwable getCause() {
return null;
}
@Override
public String getMessage() {
return toString();
}
@Override
public void printStackTrace(PrintWriter s) {
super.printStackTrace(s);
}
@Override
public void printStackTrace(PrintStream s) {
super.printStackTrace(s);
}
}
现在让敢死队来构建它:
package chuck;
import javassist.*;
public class Expendables {
private static Class clz;
public static ChuckNorrisException getChuck() {
try {
if (clz == null) {
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("chuck.ChuckNorrisException");
cc.setSuperclass(pool.get("java.lang.Object"));
clz = cc.toClass();
}
return (ChuckNorrisException)clz.newInstance();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
最后是Main类:
package chuck;
public class Main {
public void roundhouseKick() throws Exception {
throw Expendables.getChuck();
}
public void foo() {
try {
roundhouseKick();
} catch (Throwable ex) {
System.out.println("Caught " + ex.toString());
}
}
public static void main(String[] args) {
try {
System.out.println("before");
new Main().foo();
System.out.println("after");
} finally {
System.out.println("finally");
}
}
}
使用以下命令编译并运行它:
java -Xverify:none -cp .:<path_to_javassist-3.9.0.GA.jar> chuck.Main
您将得到以下输出:
before
finally
这并不奇怪,毕竟这是一个回旋踢:)
是否有可能在java中构造一段代码,使假设的java.lang. chucknorrisexception无法捕获?
是的,这就是答案:设计你的java.lang.ChuckNorrisException,使它不是java.lang.Throwable的实例。为什么?从定义上讲,不可抛出的对象是不可捕获的,因为你永远不能捕获永远不能抛出的东西。
在构造函数中,可以启动一个反复调用originalThread的线程。停止(ChuckNorisException.this)
线程可以重复捕获异常,但会一直抛出异常,直到异常死亡。