java - 在 java 中,为什么 Exception 是基类而不是 RuntimeException?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17630436/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
java - In java, why is Exception the base class and not RuntimeException?
提问by AStupidNoob
The Java specification requires that if an exception is thrown, it is either handled by a try/catch statement, or that the function is declared with "throws XYZException". This has the exception of RuntimeException, where it is OK if this is thrown without being caught.
Java 规范要求,如果抛出异常,要么由 try/catch 语句处理,要么使用“throws XYZException”声明函数。这有 RuntimeException 的例外,如果它被抛出而没有被捕获,那么它是可以的。
This might sound like a matter of opinion, but the more I think about it, the more it seems really counter-intuitive:
这听起来可能是一个意见问题,但我越想越觉得它真的违反直觉:
Why is it that we have a RuntimeException extending Exception?
为什么我们有一个 RuntimeException 扩展 Exception?
When I first started doing Java, I thought ALL exceptions had to be caught in that way, and it made sense because all exceptions extend Exception. It seems like a violation of OOP to have a RuntimeException exception exception :P. Since RuntimeException makes throws kinda redundant, why didn't Java allow all exceptions at runtime in the first place, adding a throws only when you want to force the caller to handle that type of exception?
当我第一次开始使用 Java 时,我认为所有异常都必须以这种方式捕获,这是有道理的,因为所有异常都扩展了 Exception。出现 RuntimeException 异常似乎违反了 OOP :P。既然 RuntimeException 使得 throws 有点多余,为什么 Java 一开始就不允许所有异常在运行时出现,只在您想强制调用者处理那种类型的异常时才添加 throws?
Examples:
例子:
void noThrows() {
throw new Exception();
}
... no errors.
...没有错误。
void hasThrows() throws AnyBaseOfXYZException {
throw new XYZException();
}
... no errors.
...没有错误。
void testFunction() {
hasThrows();
}
... fails since "hasThrows" throws AnyBaseOfXYZException, and this is not handled
... 失败,因为“hasThrows”抛出 AnyBaseOfXYZException,并且没有处理
void testFunction() {
try {
hasThrows();
} catch (AnyBaseOfXYZException e) {
...
}
}
... no errors.
...没有错误。
I'd thought about maybe some kind of "CompileTimeException" that extends Exception, but when you give it enough thought, it just can't work without being as ugly as RuntimeException.
我想过可能是某种扩展 Exception 的“CompileTimeException”,但是当你考虑得足够多时,它就无法正常工作而不像 RuntimeException 一样丑陋。
Basically, why did Java decide to force all exceptions to require throws
except for RuntimeExceptions, when all exceptions could be runtime exceptions except when otherwise stated with throws
?
基本上,为什么 Java 决定强制throws
除 RuntimeExceptions 之外的所有异常都需要,当所有异常都可以是运行时异常时,除非另有说明throws
?
回答by Bohemian
Firstly, the base class of all things that can be thrown is Throwable
(not Exception
).
首先,所有可以抛出的东西的基类是Throwable
(not Exception
)。
Under Throwable
are two subclasses: Exception
and Error
.
下面Throwable
是两个子类:Exception
和Error
。
Under Exception
is RuntimeException
.
下面Exception
是RuntimeException
。
Of these 4 main classes, RuntimeException
and Error
are unchecked(may be thrown without having to be declared as being thrown).
在这 4 个主要类中,RuntimeException
和Error
是未经检查的(可以抛出而不必声明为被抛出)。
The idea behind RuntimeException
being unchecked is that it's typically a programmingerror and that normal good practice should avoid them (eg ArrayIndexOutOfBoundsException
or NullPointerException
) and to require them to be caught would clutter up the code massively.
RuntimeException
未经检查背后的想法是,它通常是一个编程错误,正常的良好实践应该避免它们(例如ArrayIndexOutOfBoundsException
或NullPointerException
),并且要求它们被捕获会使代码大量混乱。
The reason Errors
are unchecked is that basically, there's nothing you can to about it if one happens, eg OutOfMemoryError
etc.
Errors
未经检查的原因是,基本上,如果发生这种情况,您无能为力,例如OutOfMemoryError
等。
That leaves all other Throwables, ie subclasses of Exception
, must be declared as thrown or caught. The idea behind this is that checked exceptions can be "handled by the caller". eg FileNotFoundException
(we know what this means and should know what to do if we get one).
这使得所有其他 Throwables,即 的子类Exception
,必须声明为抛出或捕获。这背后的想法是检查异常可以“由调用者处理”。例如FileNotFoundException
(我们知道这是什么意思,如果我们得到一个应该知道该怎么做)。
The Java designers didn't always get this right. SQLException
is checked, but there's no realistic way to recover - do I have a syntax error in my query? is the database refusing conections? who knows, but I do know I can't "handle" it.
Java 设计者并不总是正确地做到这一点。SQLException
已检查,但没有实际的恢复方法 - 我的查询中是否存在语法错误?数据库拒绝连接?谁知道,但我知道我无法“处理”它。
回答by Itay Maman
In some cases you want to have a catch
that catches all exceptions: checked and unchecked.
Java's design decision allows you to achieve that with catch (Exception e) { ... }
If unchecked exceptions (exceptions that extends RuntimeException) were not extending Exception
then you had to use two catch
clauses.
在某些情况下,您希望有一个catch
捕获所有异常的方法:已检查和未检查。Java 的设计决策允许您通过catch (Exception e) { ... }
如果未检查的异常(扩展 RuntimeException 的异常)没有扩展Exception
那么您必须使用两个catch
子句来实现。
回答by Nuntipat Narkthong
This might be related to topic of check and uncheck exception. From RuntimeException
这可能与检查和取消检查异常的主题有关。从运行时异常
RuntimeException and its subclasses are unchecked exceptions. Unchecked exceptions
do not need to be declared in a method or constructor's throws clause if they can
be thrown by the execution of the method or constructor and propagate outside the
method or constructor boundary.
Check exception is to be use for case that recoverable when the program is executed. So it makes perfect sense to force programmer writing the class to declare it in a method definition. By doing so the caller will be force to catch it or re throw it.
检查异常用于程序执行时可恢复的情况。因此,强制程序员编写类在方法定义中声明它是非常有意义的。通过这样做,调用者将被迫抓住它或重新抛出它。
However uncheck exception is for a case that is unrecoverable and thus it is better to terminate. This case is rarely happen (usually happen when the code is still being developed) and thus this usually indicate a programmer error or a very fatal bug that usually need to fix by the class writer and is not recoverable by the client of the class.
但是 uncheck 异常是针对不可恢复的情况,因此最好终止。这种情况很少发生(通常发生在代码仍在开发中时),因此这通常表示程序员错误或非常致命的错误,通常需要由类编写者修复并且类的客户端无法恢复。