为什么 main() 方法允许声明异常?

Why is main() method allowed to declare exceptions?

"Handle or declare. That's the law." - Head First

但是,这是好法吗?先举个例子:

public static void main(String[] args) throws Exception {
    m1();
}

static void m1() throws Exception{
    m2();
}

static void m2() throws Exception {
    throw new Exception();
}

m2() 抛出异常并且m1()调用m2(),这意味着它必须处理或者声明它。嗯,让我们声明吧。然后 main() 调用 m1() 并且它有相同的轮询:declarehandle。我再次决定声明它并且代码编译得很好。

好的,它有效,但是到底是谁处理了这个异常?好像没人做过我知道我是初学者,但我不喜欢这样的说法。是的,有些方法可以决定是declare还是handle异常,但为什么是main()呢? main 方法不应该是一个只处理的方法吗?如此一来,便无一例外地“溜”了。

我错过了什么吗?老实说,我很惊讶 main 方法只声明异常是可以的,因为知道这是 最后一个地方 我们可以在技术上捕获一些东西。

应用程序可能包含多个 class 主方法。在这种情况下,应用程序应该声明一个清单以了解哪个 main 是入口点(第一个调用的方法)。 Main 方法可以从另一个方法或另一个 main 方法作为静态方法调用,并且可以抛出任何异常。如果你至少在入口点没有捕获异常,那么异常从你的应用程序 returned 到 java 虚拟机,然后 mashine 决定如何处理异常。通常 jvm 向操作系统打印错误消息和 return 0 以外的值。

who handled this exception at all?

Java 运行时。

更具体地说,UncaughtExceptionHandler did, as specified in the Java Language Specification (JLS), section 11.3. Run-Time Handling of an Exception:

If no catch clause that can handle an exception can be found, then the current thread (the thread that encountered the exception) is terminated. Before termination, all finally clauses are executed and the uncaught exception is handled according to the following rules:

  • If the current thread has an uncaught exception handler set, then that handler is executed.

  • Otherwise, the method uncaughtException is invoked for the ThreadGroup that is the parent of the current thread. If the ThreadGroup and its parent ThreadGroups do not override uncaughtException, then the default handler's uncaughtException method is invoked.

因此,默认情况下,当 main() 抛出异常时,未检查或检查,built-in 默认的“未捕获异常处理程序”将简单地将堆栈跟踪打印到 System.err,as-if 以下是在调用 main() 之前执行的:

Thread.setDefaultUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler());
class DefaultUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        e.printStackTrace();
    }
}

调用“未捕获的异常处理程序”后,线程将终止,就像您只是从 main() 方法 return 一样,除非代码已启动 non-daemon线程仍然 运行,程序结束。