Java 你为什么要抓住“你为什么要抓住我?”;例外情况;但不是子类;运行时异常";?
下图显示“已检查”和“未检查”异常是Java 你为什么要抓住“你为什么要抓住我?”;例外情况;但不是子类;运行时异常";?,java,exception,exception-handling,Java,Exception,Exception Handling,下图显示“已检查”和“未检查”异常是异常的子类。我发现您需要捕获异常,但不需要捕获直接从异常继承的运行时异常,这让人感到困惑。开发人员为什么不让我们在不需要捕获异常的情况下抛出异常 更具体地说:为什么只能忽略运行时异常及其子项?为什么没有引入一个名为CheckedException extends Exception的类,而您只需要捕获它及其子类 令人困惑的是,您可以毫无疑问地抛出RuntimeException下面的所有内容,但是当您在层次结构中向上移动到Exception时,您需要在某个点捕
异常的子类。我发现您需要捕获异常
,但不需要捕获直接从异常继承的运行时异常
,这让人感到困惑。开发人员为什么不让我们在不需要捕获异常的情况下抛出异常
更具体地说:为什么只能忽略运行时异常
及其子项?为什么没有引入一个名为CheckedException extends Exception
的类,而您只需要捕获它及其子类
令人困惑的是,您可以毫无疑问地抛出RuntimeException
下面的所有内容,但是当您在层次结构中向上移动到Exception
时,您需要在某个点捕获它。这是令人困惑的,因为“抽象”通常在其他情况下起作用。你越往上爬,每件事就变得越简单、越复杂。这里的情况并非如此。你越往上爬,你需要做的事情就越多(比如,在到达异常后放置try/catch)
检查异常
(确实存在)和运行时异常
都扩展了异常
。因此,如果某个东西抛出一个通用的异常
(这总是一个坏主意),则无法判断该异常是一个还是另一个,因此您必须捕获它,以防它是选中的。如果你用这种方式来考虑层次结构,它实际上会变得越简单
您似乎认为已检查异常更“复杂”,因为您必须做更多的工作来解决它们。这种想法不太健康。相反,考虑一下:异常是程序本身的问题——代码。我们需要找到这些异常并妥善处理它们。在已经有了异常处理的概念之后,我们发现存在一些我们无法预测的问题
“当要求输入整数时,我怎么知道用户会输入‘喵喵’!我不应该对此进行编码!”因此,NumberFormatException
诞生了,您不必捕捉它,因为这是一个“逻辑错误”,而不是由错误代码引起的问题(尽管可以说,如果您不以某种方式处理这种情况,它可能被认为是糟糕的代码)
简而言之,改变你的想法。Exception
s是程序中可以处理的问题。但是,也有一些异常是意外的,并且是由于糟糕的设计而不是错误的代码造成的。因此,添加了RuntimeException
s,这是不可能发生的,但肯定会发生cur.假设他们以另一种方式设计它。我们有一个CheckedException
类,需要处理它的子类,但没有Exception
的其他子类
现在我们调用一个可能引发任意异常的方法:
public static void example() {
functionThatThrowsException();
}
我们需要处理它吗?是,因为异常
可能是一个检查异常
。如果我们不需要处理它,我们将绕过检查异常的检查性质
具有选中子体的可丢弃类型必须被视为选中类型,因此选中度自然会向上传播到继承层次结构中。相反,未选中的可丢弃类型不能具有选中的子体,因此不选中度自然会向下传播。这使得将选中度设为默认值并挑出特定类是很自然的而它们的后代则未经检查。也许从继承的角度考虑异常类会有所帮助,但简单地说就是不相交的类集合,一个集合被检查,另一个不被检查。您是对的,可能存在一个CheckedException
类,允许我们仅在明确指定的情况下进行检查
然而,检查更广泛的/通用的范围有助于强制执行模式。检查异常允许代码读者快速发现这段代码需要特别注意,并在编译时强制执行它们的处理,从而减少运行时错误
我们可以抛出任何类型的异常,无论是选中的还是未选中的。如果exception
或RuntimeException
的任何超类被设置为选中的异常,那么所有的子类都将成为选中的异常。因为编译器最有可能在throws子句中检查异常实例或类是否派生自类通过检查一个可能更适合被检查或取消检查的特定包,可以很容易地做到这一点,因为它与继承无关。如果异常被取消检查,那么您可以隐式地将检查的异常转换为未检查的异常,这意味着您可以抛出che在不捕获异常的情况下对异常进行检查,如:
public void f() {
Exception e = new IOException();
throw e;
}
此外,对于重写方法,如果抛出更具体的异常,可以添加捕获不在超类中的异常的要求:
public void f() throws Exception {
}
...
@Override
public void f() throws IOException {
}
您的图片已经包含一个答案-Throwable
被选中并且必须被捕获,因为除了RuntimeException
及其子体之外,Exception
被选中等等
选中的异常必须捕获或重新捕获()。这是java编译器保证的,因此我们可以确保“异常”情况得到处理
此编译时检查是否存在异常处理程序是必要的
旨在减少未正确处理的异常数量
处理
如果颠倒逻辑,则无法在编译时提供以下保证:
public void notReallySafeMethod() {
try {
connect();
} catch (IOException io) {
Exception e = io;
throw e; // IOException is unhandled
}
}
public void suspiciousMethod() throws Exception {};
public void callSuspicious() {
suspiciousMethod(); // what real type would be thrown? we can't know
// should I try-catch everything then?
}
我想如果你捕捉到异常,你会捕捉到所有的异常以及该异常类的所有死者