是否可以仅通过查看代码来判断异常类是已选中还是未选中?我一直认为,如果它扩展了 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 虚拟机通过相同的过程搜索该方法的异常表。