是否可以在没有任何 athrow 指令的情况下隐式抛出已检查的异常?

cbc*_*olf 0 java exception checked-exceptions unchecked-exception

在 Java 中,检查异常和未检查异常都可以显式抛出,即通过throw语句抛出。此外,未经检查的异常如ArithmeticExceptionOutOfMemoryError可以在没有任何显式throw声明的情况下触发,如下所示:

public static void throwArithmeticException() {
    int i = 1;
    int j = i / 0;
}

public static void throwOutOfMemoryError() {
    List<Object> list = new ArrayList<>();
    while(true) {
        list.add(new Object());
    }
}
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,有没有什么方法可以触发检查的异常,例如IOException隐式,即不使用任何throw语句?

Ste*_*n C 5

你可以做到,但你不应该1

我假设您在谈论athrow字节码指令。(而且您确实在问是否可以不使用throw语句的情况下从代码中触发异常。)

应用程序有(至少)两种方式抛出不涉及显式athrow指令的任意 Java 异常(已检查或未检查)。

  1. 你可以打电话Unsafe.throwException(Throwable)

  2. 在本机代码中,您可以调用JNI API 中的ThrowThrowNew函数。

在这两种情况下,您都可以绕过 Java(编译时和验证器)检查,这些检查旨在确保始终声明(通过throws子句)或处理已检查的异常。

请注意,使用Unsafe或本机代码意味着您的代码不是纯 Java。它不会是便携式的。此外,很容易做一些会使 JVM 不稳定的事情。JVM 崩溃并不少见。


此外,JVM 本身会在没有athrow指令的情况下抛出异常。例如,如果您尝试使用new FileInputStream打开一个不存在并被FileNotFoundException抛出的文件,它是从本机代码中抛出的,而不是从编译后的 Java 代码中抛出。

因此,您的应用程序可以使用此机制隐式抛出许多已检查和未检查的异常;例如,故意尝试打开一个不存在的文件。但是,for 的方法签名read声明它可能抛出IOException,所以编译器知道这个......从检查异常规则的角度来看。


1 - 如果您的应用程序设计需要这种疯狂,我们建议您想出一个替代方案。试图对抗 Java 的检查异常规则是一个坏主意。如果你非常不喜欢它们以至于你正在考虑这个,你应该选择一种不同的编程语言。

  • 是的。“Unsafe”是其 API 中特定的实现。最重要的是,“安全地”使用“不安全”还有各种实现特定的方面……如果你明白我的意思的话。 (2认同)