投掷新的NPE时不需要Java’抛出’条款? 为什么添加“throws Exception”会出现编译错误?

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

本问题已经有最佳答案,请猛点这里访问。

我对'throws'子句感到好奇,并编写了下面的一段代码(我使用Eclipse和Java7)。 最初我只使用第1和第5块开始(期待编译错误,但没有发生......)然后这导致我编写其他块。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 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.中的编译错误(未处理的异常?我的方法不应该通知任何'后续调用者'这会抛出某种异常吗?)

(b)4中的某种问题(可能是编译错误?我在IAE中抛出NPE)

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

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


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

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

异常(所有已检查的异常都继承自此异常)

RuntimeException(所有未经检查的异常都从此继承)

所有都是Throwables


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

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

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

3)与第一个答案相同

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

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

6)尽管你在throwNPEWithGenericClause中抛出NullPointerException(RuntimeException),因为你将方法标记为checked exception,编译器不允许。

7,8)与第一个答案相同。两个运行时异常,无需检查。


RuntimeException或未经检查的异常实例(如NPE)不需要抛出/捕获。它们可以被捕获,但通常你不想这样,因为它表示程序流程异常,它应该终止程序。通常,如果没有可能继续,那么它将作为RuntimeException终止。如果要阻止对null值执行某种操作,则应检查它是否为null而不是期望NPE。