Java 'throws' 抛出新的 NPE 时不需要子句?为什么添加 "throws Exception" 会导致编译错误?

Java 'throws' clause not needed when throwing a new NPE? and why does adding "throws Exception" give compilation errors?

我对 'throws' 子句感到好奇并编写了以下代码(我将 Eclipse 与 Java7 一起使用)。最初我只从 15 块开始(预计会出现编译错误,但并没有发生......)然后这让我想到写其他块。

// 1
public void throwNPE() {
    throw new NullPointerException();
}

// 2
public void throwNPEWithGenericClause() throws Exception {
    throw new NullPointerException();
}

// 3
public void throwNPEWithNPEClause() throws NullPointerException {
    throw new NullPointerException();
}

// 4
public void throwNPEWithIAEClause() throws IllegalArgumentException {
    throw new NullPointerException();
}

// 5
public void callThrowNPE() {
    throwNPE();
}

// 6
public void callThrowNPEWithGenericClause() {
    throwNPEWithGenericClause(); // COMPILATION ERROR
}

// 7
public void callThrowNPEWithNPEClause() {
    throwNPEWithNPEClause();
}

// 8
public void callThrowNPEWithIAEClause() {
    throwNPEWithIAEClause();
}

老实说,我的预期是:

(a) 1 中的编译错误。(未处理的异常?我的方法不应该通知任何 'subsequent caller' 这将引发某种异常?)

(b) 4 中的某种问题。(可能是编译错误?当子句说 IAE 时我正在抛出 NPE)

(c) 5. 6. 7. 和 8. 中的编译错误(未处理的异常?我省略了 'throws' 子句)

(d) 也许有人也可以告诉我为什么 6. 是唯一一个出现编译错误的...

RuntimeException 或 NPE 等未经检查的异常实例不需要 throwing/catching。它们可以被捕获,但通常你不想这样做,因为它表明程序流程异常并且应该终止程序。通常,如果无法继续,它将作为 RuntimeException 终止。如果您想防止对空值执行某种操作,那么您应该检查它是否为空,而不是期待 NPE。

Java中的异常可以分为三种不同的基本类型:

Error(由 JVM 抛出,如果发生致命错误)

Exception(所有检查异常都继承自这个)

RuntimeException(所有unchecked Exception都继承自此)

都是Throwables

RuntimeException 未选中,因此当您抛出 RuntimeException 的异常子类时,编译器不会发出警告。如果您需要编译器警告您,那么您应该使用 Exception 或其子类。

1) NullPointerException extends RuntimeException 所以编译器不会给出任何错误。

2) 即使您的方法抛出 NullPointerException,因为您用 throws Exception 标记了该方法,编译器会警告您在它的调用者中捕获它。

3) 同第一个答案

4) 与第一个答案相同 IllegalArgumentException extends RuntimeException

5) throwNPE 根本不抛出任何东西。

6) 尽管您在 throwNPEWithGenericClause 中抛出 NullPointerException (RuntimeException),但由于您将该方法标记为检查异常,编译器不允许。

7, 8) 与第一个答案相同。都是运行时异常,不用查。