是否可以仅通过查看代码来判断异常类是已选中还是未选中?我一直认为,如果它扩展了 Exception,它就被选中了,但是 RuntimeException 扩展了 Exception 并且没有被选中。RuntimeException 可能是唯一违反该经验法则的类,如果不扩展 RuntimeException,其他未经检查的异常必须扩展 Throwable。但是,我看不出 RuntimeException 与 Exception 有何不同。我想知道差异是否在解释器本身内部定义?
8 回答
RuntimeException它的子类是未经检查的异常。所有其他都是检查异常。
是否可以仅通过查看代码来判断异常类是已选中还是未选中?
是的。如果您知道 JLS ( 11.1.1 )中指定的规则...并且您还可以查看异常超类的代码(以便您可以检查层次结构)。
规则是“检查”例外情况,但以下情况除外:
RuntimeException及其子类,以及Error及其子类,
这是“未经检查的”。
我想知道差异是否在解释器本身内部定义?
不,它在 Java 语言规范中。事实上,JVM 对已检查和未检查异常的处理是一样的。所有检查检查的异常是否被正确处理的检查都是由 Java 编译器完成的。
但是,我仍然不明白 RuntimeException 扩展 Exception 而不是 Throwable 的原因。考虑到 RuntimeException 中没有任何内容可以覆盖 Exception 中定义的行为,这种设计选择似乎是矛盾的。
它就是这样。此外,我没有看到任何逻辑上的矛盾。
An
Error表示不可恢复的状态。未选中它是因为没有必要强制应用程序对其执行某些操作。An
Exception代表一种潜在的可恢复状态。A
RuntimeException表示我们不想强制应用程序处理的潜在可恢复条件。(但它可以,如果它愿意的话)。
显然,根据这种分类法,a RuntimeException>>is<< anException和 >>not<< an Error... 这就是以这种方式定义异常类层次结构的基本原理。
您可以在Java 教程(强调我的) 中找到未检查异常的定义:
... Java 编程语言不需要方法来捕获或指定未经检查的异常(RuntimeException、Error 及其子类) ...
而不是“捕获与未捕获”,它们被称为“已检查与未检查”异常。在编译时检查的异常是受控的,即编译器会在某些不符合异常合同的情况下向您发出警告,但可以在运行时抛出未经检查的异常。
如果您使用 IDE 是最简单的方法,如果您的 IDE 给您一个错误/下划线,告诉您当您没有捕获它时您有一个未处理的异常。那些是检查异常。
或者,从 RuntimeException 继承的任何内容都未选中。
如果您使用任何throws exception明确的方法或代码,则需要捕获该异常,并且通过查看代码,我们确定我们需要捕获,因此已检查Exception。如果RuntimeException通过查看代码,您无法确保此代码会引发异常,因此它们未被选中。
Java 文档参考
方法可以抛出的任何异常都是该方法的公共编程接口的一部分。调用方法的人必须知道方法可以抛出的异常,以便他们可以决定如何处理它们。这些异常与其参数和返回值一样,都是该方法编程接口的一部分。
继承树Throwable实际上是:
可抛出错误
异常运行时异常
抛出任何延伸Error或RuntimeException不需要声明的地方。错误通常只由 JVM 抛出,并表示发生了非常糟糕的事情。
任何扩展Exception但不扩展的东西RuntimeException都需要声明。通常Exceptions是调用代码应该处理或考虑的事情(例如“无法打开文件”),而RuntimeExceptions可能表明代码中存在错误或数据损坏的事情,NullPointerException因此调用代码不太可能做关于它的任何事情。
正如javadoc所说:
RuntimeException 是可以在 Java 虚拟机正常运行期间抛出的那些异常的超类。方法不需要在其 throws 子句中声明任何可能在方法执行期间抛出但未被捕获的 RuntimeException 子类。
作者:弗兰克·耶林
自:JDK1.0
现在,回到您的问题,I wonder if the difference is defined inside the interpreter itself?....魔术是在bytecode中完成的。
下面的文章通过分析字节码来展示它:
基本机制是 异常表:
Exception table:
from to target type
0 4 4 <Class java.lang.ArithmeticException>
如果在方法执行期间抛出异常,Java 虚拟机将在异常表中搜索匹配条目。
如果当前程序计数器在条目指定的范围内,并且抛出的异常类是条目指定的异常类(或者是指定异常类的子类),则异常表条目匹配。
Java 虚拟机按照条目在表中出现的顺序搜索异常表。当找到第一个匹配项时,Java 虚拟机将程序计数器设置为新的 pc 偏移位置并继续在那里执行。
如果未找到匹配项,Java 虚拟机将弹出当前堆栈帧并重新引发相同的异常。
当 Java 虚拟机弹出当前堆栈帧时,它有效地中止当前方法的执行并返回到调用此方法的方法。但不是在前一个方法中继续正常执行,而是在该方法中抛出相同的异常,这导致 Java 虚拟机通过相同的过程搜索该方法的异常表。