java—在java中,为什么Exception是基类而不是RuntimeException?

java—在java中,为什么Exception是基类而不是RuntimeException?,java,exception,Java,Exception,Java规范要求,如果抛出异常,它要么由try/catch语句处理,要么用“throws XYZException”声明函数。这有RuntimeException的异常,如果在没有被捕获的情况下抛出,则可以 这听起来可能是一个观点问题,但我越想它,它就越显得违反直觉: 为什么我们有一个RuntimeException扩展异常 当我第一次开始使用Java时,我认为所有异常都必须以这种方式捕获,这是有意义的,因为所有异常都扩展了异常。有RuntimeException似乎违反了OOP:P。既然Run

Java规范要求,如果抛出异常,它要么由try/catch语句处理,要么用“throws XYZException”声明函数。这有RuntimeException的异常,如果在没有被捕获的情况下抛出,则可以

这听起来可能是一个观点问题,但我越想它,它就越显得违反直觉:

为什么我们有一个RuntimeException扩展异常

当我第一次开始使用Java时,我认为所有异常都必须以这种方式捕获,这是有意义的,因为所有异常都扩展了异常。有RuntimeException似乎违反了OOP:P。既然RuntimeException使得抛出有点多余,为什么Java一开始就不允许运行时出现所有异常,只在您希望强制调用方处理该类型的异常时才添加抛出

示例:

void noThrows() {
    throw new Exception();
}
。。。没有错误

void hasThrows() throws AnyBaseOfXYZException {
    throw new XYZException();
}
void testFunction() {
    hasThrows();
}
。。。没有错误

void hasThrows() throws AnyBaseOfXYZException {
    throw new XYZException();
}
void testFunction() {
    hasThrows();
}
。。。失败,因为“hasThrows”抛出AnyBaseOfXYZEException,而这不会被处理

void testFunction() {
    try {
        hasThrows();
    } catch (AnyBaseOfXYZException e) {
        ...
    }
}
。。。没有错误

void hasThrows() throws AnyBaseOfXYZException {
    throw new XYZException();
}
void testFunction() {
    hasThrows();
}
我曾考虑过某种扩展异常的“CompileTimeException”,但当您充分考虑它时,它就无法像RuntimeException那样丑陋地工作


基本上,为什么Java决定强制所有异常都需要
抛出
,除了运行时异常,而所有异常都可以是运行时异常,除非用
抛出
另有说明?

在某些情况下,您希望捕获所有异常的
捕获
:选中和取消选中。 Java的设计决策允许您通过
catch(异常e){…}

如果未检查的异常(扩展RuntimeException的异常)未扩展
异常
,则必须使用两个
catch
子句。

这可能与检查和取消检查异常主题有关。从运行时异常

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.
检查异常用于程序执行时可恢复的情况。因此,强制编写类的程序员在方法定义中声明类是非常有意义的。通过这样做,呼叫者将被迫抓住它或重新抛出它


但是,取消选中例外适用于无法恢复的情况,因此最好终止。这种情况很少发生(通常发生在代码仍在开发时),因此这通常表示程序员错误或非常致命的错误,通常需要由类编写器修复,并且类的客户端无法恢复。

首先,可以抛出的所有东西的基类都是可抛出的
Throwable
(非
异常

Throwable
下有两个子类:
Exception
Error

Exception
下是
RuntimeException

在这4个主要类中,
RuntimeException
Error
未选中(可以在不必声明为被抛出的情况下抛出)

取消选中
RuntimeException
背后的想法是,这通常是一个编程错误,正常的良好实践应该避免它们(例如
ArrayIndexOutOfBoundsException
NullPointerException
),并且要求捕获它们会使代码大量混乱

错误
被取消选中的原因是,基本上,如果发生错误,您无法对此进行任何处理,例如
OutOfMemoryError

这就留下了所有其他可丢弃的,即
异常的子类必须声明为抛出或捕获。其背后的思想是,已检查的异常可以“由调用方处理”。例如
FileNotFoundException
(我们知道这意味着什么,如果我们得到一个异常,应该知道该怎么办)


Java设计者并不总是正确的。检查了
SQLException
,但没有实际的恢复方法-我的查询中是否有语法错误?数据库是否拒绝连接?谁知道,但我知道我无法“处理”它。

我明白,我的观点是,既然RuntimeException扩展了异常,那么抛出RuntimeException的函数也会抛出异常,因此应该声明
抛出异常
。这很混乱,我想知道为什么Java会在所有异常都可能是运行时异常的情况下做出这样的选择ns,除非另有说明。这不是我的意思。我想知道为什么,默认情况下,除非另有说明,否则异常不是所有运行时异常。默认情况下,异常不是“选中的”。每当您编写新的异常类时,您必须指定其超类。如果您指定“exception”,它将被选中。如果您指定“runtime exception”,它将被取消选中。没有默认设置。您必须显式设置其类别。我知道您在说什么,我也理解。因为我可以创建一个扩展Exception并抛出它的类,所以我仍然需要抛出Exception来允许它编译。但对于RuntimeException:即使它扩展了Exception,也不需要抛出。这使它看起来像在Java,没有办法抛出未经检查的异常。当我学习Java时,我只是假设了这一点。只有当我搜索如何抛出未经检查的异常时,我才发现了RuntimeException。我只是好奇为什么它是这样设计的,所以感谢您的回答。啊,好吧,我不知道可丢弃的
错误
。现在事情变得更有意义了。不过,你知道为什么他们会强制默认捕获所有异常吗?@AStupidNoob他们不会强制默认捕获所有异常,只会检查异常;这些是
异常
的子类,除了
运行时异常
和子类。我的问题是关于RuntimeException扩展了Exception这一事实,因此正如我可以创建Exc的子类一样