关于受检查和未经检查的异常的问题在这里和其他网站上已经提出了数百万次,但是我仍然对如此不同的答案感到困惑。
在许多答案和文章中,我们可以阅读以下常规声明:
未经检查的运行时异常通常表示以下情况:
讲,在程序逻辑中反映错误,不能
从运行时合理地恢复。
和检查异常
表示在以下人员的直接控制范围之外的无效条件
程序(无效的用户输入,数据库问题,网络中断,
缺少文件)
这两个引号均来自http://www.javapractices.com/topic/TopicAction.do?Id=129,并被多次引用。
我们可以在oracle网站上阅读类似的声明:
运行时异常表示由于以下原因导致的问题:
编程问题,因此,API客户端代码无法
有理由期望他们从他们那里康复或处理他们
方式
http://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html
让我们举一个简单的例子,用Scanner读取Number:
Scanner sc = new Scanner(System.in);
int userInput = sc.nextInt();
System.out.println(userInput);
当我键入“ asdf”而不是int时,nextInt()会引发InputMismatchException。 InputMismatchException是RuntimeException,但根据上述声明,这是已检查的异常“无效的用户输入”的第一个示例。
当我查看检查的异常时,我会更加困惑。例如NPE与FileNotFoundException-可以通过简单的if-else防止两者,那么为什么不选中第一个,然后选中第二个呢?
Oracle网站有底线准则:
如果可以合理预期客户会从异常中恢复过来,
使其成为检查异常。如果客户无能为力
从异常中将其设为未经检查的异常。
因此,据此我可以从FileNotFoundException或IOException中恢复,但不能从NPE或ArrayIndexOutOfBoundsException中恢复吗?这是没有道理的。
也许有人用一些更好的例子对此有更好的解释?
参考方案
简单实用:
未检查的异常(Runtime
类和子级)传达了意外的异常。
通常,调用者不应该知道如何处理它,并且在任何情况下都不要等待它。
被检查的异常传达了一个异常,您可以将其视为“正常”异常,并且调用方知道如何处理该异常。对于他来说,这可能不是名义上的情况,但呼叫者知道这可能会发生,因此应该做好应对的准备。
在您的示例中:
nextInt() throws
InputMismatchException
当我键入“ asdf”时
而不是int。 InputMismatchException
是RuntimeException
但
根据上面的陈述,这是选中的第一个示例
例外“无效的用户输入”。
当方法调用nextInt()
时,调用方将等待int
值。这是例外情况。如果不是这种情况,则用户宁愿:next()
检索String对象,然后尝试通过合适的方式将其转换。
当您调用nextInt()
时,调用方将按其要求等待int
。强迫他处理InputMismatchException
,因为选中的Exception
将违反直觉。
因此,据此我可以从FileNotFoundException或
IOException但我不能从NPE或ArrayIndexOutOfBoundsException吗?
这是没有道理的。
我认为FileNotFoundException
或IOException
的JDK异常是特殊情况。可能不一定要检查它们,因为这些类的客户端等待未找到文件或流在读取或写入期间生成一些异常,而是因为流可能处于不合适的状态,并因此由于许多外部原因而引发异常(文件已锁定,权限不足,文件已移至其他地方或无法访问的网络,等等)。
生成异常的文件可能被认为是重要的处理内容。
因此,JDK规范希望调用者显式地对其进行处理。
此外,在try-with-resources语句到达之前,调用程序应显式关闭流,以防出现异常。
NPE
和ArrayIndexOutOfBoundsException
通常是编程错误。应用程序无法进行处理以恢复不知道存在的特定错误。那么为什么要检查它们呢?
试图绕过Java并发问题,并且很难理解线程池,线程以及它们正在执行的可运行“任务”之间的关系。如果我创建一个有10个线程的线程池,那么我是否必须将相同的任务传递给池中的每个线程,或者池化的线程实际上只是与任务无关的“工人无人机”可用于执行任何任务?无论哪种方式,Executor / ExecutorService如何将正确的任务分配给正确的线程? 参考方案 …
JAVA:字节码和二进制有什么区别? - javajava字节代码(已编译的语言,也称为目标代码)与机器代码(当前计算机的本机代码)之间有什么区别?我读过一些书,他们将字节码称为二进制指令,但我不知道为什么。 参考方案 字节码是独立于平台的,在Windows中运行的编译器编译的字节码仍将在linux / unix / mac中运行。机器代码是特定于平台的,如果在Windows x86中编译,则它将仅在Win…
java:继承 - java有哪些替代继承的方法? java大神给出的解决方案 有效的Java:偏重于继承而不是继承。 (这实际上也来自“四人帮”)。他提出的理由是,如果扩展类未明确设计为继承,则继承会引起很多不正常的副作用。例如,对super.someMethod()的任何调用都可以引导您通过未知代码的意外路径。取而代之的是,持有对本来应该扩展的类的引用,然后委托给它。这是与Eric…
Java:BigInteger,如何通过OutputStream编写它 - java我想将BigInteger写入文件。做这个的最好方式是什么。当然,我想从输入流中读取(使用程序,而不是人工)。我必须使用ObjectOutputStream还是有更好的方法?目的是使用尽可能少的字节。谢谢马丁 参考方案 Java序列化(ObjectOutputStream / ObjectInputStream)是将对象序列化为八位字节序列的一种通用方法。但…
Java DefaultSslContextFactory密钥库动态更新 - java我有一个使用org.restlet.engine.ssl.DefaultSslContextFactory的现有应用程序和一个在服务器启动时加载的密钥库文件。我有另一个应用程序,该应用程序创建必须添加的证书服务器运行时动态地更新到密钥库文件。为此,我在代码中创建了证书和私钥,然后将其写入到目录。该目录由bash脚本监视,该脚本检查是否有新文件,如果出现,它将…