![]() |
1
187
只要你知道什么时候应该使用它们,检查异常就很好。Java核心API未能遵循SQLException(有时甚至IOException)的这些规则,这就是它们如此糟糕的原因。 检查违例 应用于 可预测的 但是 不可预防的 错误是 合理的恢复 . 不检查违例 应该用于其他所有事情。 我会为你详细解释一下,因为大多数人误解了这意味着什么。
除非你抛出的异常满足 所有 在上述条件中,它应该使用Unchecked Exception。 在各个层面重新评估 :有时捕获已检查异常的方法不是处理错误的正确位置。在这种情况下,考虑一下对你自己的来电者来说什么是合理的。如果异常是可预测的、不可预防的,并且他们可以从中恢复,那么你应该自己抛出一个已检查的异常。如果没有,则应将异常包装为未选中的异常。如果你遵循这条规则,你会发现自己将选中的异常转换为未选中的异常,反之亦然,具体取决于你所在的层。
对于已检查和未检查的异常,
使用正确的抽象级别
例如,具有两个不同实现(数据库和文件系统)的代码存储库应避免通过抛出
|
![]() |
2
55
来自 A Java Learner :
|
![]() |
3
45
情况正好相反: 从不 使用已检查的例外情况。我不愿意在辩论中偏袒任何一方(双方都有很好的论点!),但相当多的专家认为,事后看来,检查例外是一个错误的决定。 有关讨论,请查看WikiWikiWebs âChecked exceptions are of dubious valueâ 另一个早期广泛争论的例子是 Rod Waldhoffâs blog post . |
![]() |
4
38
在任何足够大、有很多层的系统上,检查异常都是无用的,因为无论如何,你需要一个架构级策略来处理异常的处理方式(使用故障屏障) 除了已检查的例外情况,您的错误处理策略是微观管理的,在任何大型系统上都是无法忍受的。 大多数时候,您不知道错误是否是“可恢复的”,因为您不知道API的调用方位于哪个层。 假设我创建了一个StringToInt API,它将整数的字符串表示转换为Int。如果使用“foo”字符串调用API,我是否必须抛出已检查的异常?它可以恢复吗?我不知道,因为在他的层中,我的StringToInt API的调用方可能已经验证了输入,如果抛出这个异常,那要么是bug,要么是数据损坏,这一层无法恢复。 在这种情况下,API的调用程序不想捕获异常。他只想让例外“浮出水面”。如果我选择了一个已检查的异常,则此调用者将有大量无用的catch块,只能人为地重新抛出异常。 什么是可恢复的大部分时间取决于API的调用方,而不是API的编写方。API不应使用已检查的异常,因为只有未检查的异常才允许选择捕获或忽略异常。 |
![]() |
5
28
你说得对。 未检查的例外情况 用于让系统 fail fast 这是一件好事。你应该清楚地说明你的方法需要什么才能正常工作。这样,您只能验证输入一次。 例如:
举个例子。关键是,如果系统很快失败,那么你就会知道它在哪里以及为什么失败。你会得到一个堆栈跟踪,比如:
你会知道发生了什么。“delegateTheWork”方法(第4569行)中的OtherClass使用“exit”值调用您的类,即使它不应该这样做。 否则,您将不得不在代码中到处撒验证,这很容易出错。此外,有时很难跟踪出了什么问题,您可能会期待数小时令人沮丧的调试 同样的情况也发生在NullPointerException上。如果你有一个700行的类,有大约15个方法,它使用30个属性,并且它们都不能为空,而不是在每个方法中验证可空性,你可以将所有这些属性设置为只读,并在构造函数或工厂方法中验证它们。
检查型异常 当程序员(您或您的同事)做对了一切,验证了输入,运行了测试,并且所有代码都很完美,但代码连接到可能已关闭的第三方Web服务(或您使用的文件被另一个外部进程删除等)时,它很有用。甚至可以在尝试连接之前验证Web服务,但在数据传输过程中出现了问题。 在这种情况下,你或你的同事都无能为力。但你仍然必须做点什么,不要让应用程序在用户眼中消失。您为此使用一个已检查的异常并处理该异常,当发生这种情况时,您能做什么?,大多数时候,只是为了记录错误,可能会保存您的工作(应用程序工作)并向用户显示消息。(网站blabla已关闭,请稍后重试等。 ) 如果被检查的异常被过度使用(通过在所有方法签名中添加“throw exception”),那么你的代码将变得非常脆弱,因为每个人都会忽略这个异常(因为它太笼统了),代码的质量将受到严重损害。 如果你过度使用未经检查的异常,类似的事情也会发生。经过多次尝试,该代码的用户不知道是否会出现问题{...}catch(Throwable t)将会出现。 |
![]() |
6
18
这是我的“最终经验法则”。
与之前的答案相比,这是使用一种或另一种(或两种)例外的明确理由(人们可以同意或不同意)。 对于这两个异常,我将为我的应用程序创建自己的未经检查和已检查的异常(这是一个很好的做法, as mentionned here ),除了非常常见的未经检查的异常(如NullPointerException)
例如,下面这个特定函数的目标是制作(或者如果已经存在,则获取)一个对象,
例子:
|
![]() |
7
17
这不仅仅是从异常中恢复的能力问题。在我看来,最重要的是呼叫者是否有兴趣捕捉异常。 如果你编写了一个在其他地方使用的库,或者应用程序中的较低级别层,问问自己调用者是否有兴趣捕捉(了解)你的异常。如果他不是,那么使用未经检查的异常,这样你就不会给他带来不必要的负担。 这是许多框架使用的哲学。特别是Spring和hibernate,它们将已知的已检查异常转换为未检查异常,正是因为Java中过度使用了已检查异常。我能想到的一个例子是json.org的JSONException,这是一个已检查的异常,而且大多很烦人——它应该是未检查的,但开发人员根本没有想过。 顺便说一句,大多数时候,调用者对异常的兴趣与从异常中恢复的能力直接相关,但情况并非总是如此。 |
![]() |
8
11
这里有一个非常简单的解决方案,可以解决您的选中/未选中困境。 规则1:将未检查异常视为代码执行前的可测试条件。 例如
其中x为空。.. 代码可能包含以下内容
规则2:将Checked Exception视为代码执行时可能发生的不可测试的情况。
在上面的示例中,由于DNS服务器关闭,URL(google.com)可能不可用。即使在DNS服务器工作并将google.com名称解析为IP地址的那一刻,如果连接到google.com,在任何时候,网络都可能崩溃。在读写流之前,你根本无法一直测试网络。 有时,在我们知道是否存在问题之前,代码必须执行。通过强迫开发人员以这种方式编写代码,迫使他们通过Checked Exception处理这些情况,我必须向发明这个概念的Java的创建者致敬。 一般来说,Java中的几乎所有API都遵循上述2条规则。如果您尝试写入文件,磁盘可能会在完成写入之前填满。可能是其他进程导致磁盘已满。根本没有办法测试这种情况。对于那些在任何时候使用硬件都可能失败的人来说,Checked Exceptions似乎是解决这个问题的一个优雅的解决方案。 这有一个灰色地带。如果需要进行许多测试(如果语句中有很多&and ||,这会让人大吃一惊),抛出的异常将是CheckedException,因为很难正确处理,你根本不能说这个问题是编程错误。如果测试数量远少于10个(例如If(x==null)),则程序员错误应为UncheckedException。 与语言口译员打交道时,事情会变得有趣。根据上述规则,语法错误应被视为选中异常还是未选中异常?我认为,如果语言的语法可以在执行之前进行测试,那么它应该是一个UncheckedException。如果语言不能像汇编代码在个人计算机上运行那样进行测试,那么语法错误应该是一个检查异常。 上述两条规则可能会消除你90%的选择顾虑。要总结规则,请遵循以下模式 1) 如果要执行的代码可以在执行之前进行测试,以确保其正确运行,并且如果发生异常,即程序员错误,则该异常应为UncheckedException(RuntimeException的子类)。 2) 如果要执行的代码在执行之前无法进行测试以使其正确运行,则异常应为已检查异常(异常的子类)。 |
![]() |
9
8
您可以将其称为已检查或未检查的异常;然而, 两者 程序员可以捕获异常类型,因此最好的答案是:写 所有 您的例外情况如下 不受限制的 并记录下来。这样,使用API的开发人员就可以选择是否要捕获该异常并执行某些操作。检查异常完全浪费了每个人的时间,这让你的代码看起来像是一场令人震惊的噩梦。适当的单元测试会发现你可能必须捕捉并处理的任何异常。 |
![]() |
10
7
已检查异常: 如果客户端可以从异常中恢复并希望继续,请使用选中的异常。 未检查异常: 如果客户端在异常发生后无法执行任何操作,则引发未经检查的异常。 示例:如果你希望在方法a()中进行算术运算,并且基于a()的输出,那么你必须进行另一个操作。如果方法A()的输出为null,而这是您在运行时不期望的,那么您应该抛出null指针异常,这是运行时异常。 参考 here |
![]() |
11
2
以下是我想分享我多年开发经验后的看法:
根据目标受众。现在让我们来谈谈目标受众或人群——例外情况已经设计好了(根据我的意见):
按应用程序开发生命周期阶段。
框架通常使用未经检查的异常(例如Spring)的原因是框架无法确定应用程序的业务逻辑,这取决于开发人员捕捉并设计自己的逻辑。 |
![]() |
12
2
我们必须根据是否是程序员错误来区分这两种类型的异常。
FileNotFoundException是理解细微差异的一个很好的例子。如果找不到文件,则抛出FileNotFoundException。这种例外有两个原因。如果文件路径由开发人员定义或通过GUI从最终用户处获取,则应为未选中异常。如果文件被其他人删除,则应为“已检查异常”。 检查异常可以通过两种方式处理。这些正在使用try-catch或传播异常。在异常传播的情况下,调用堆栈中的所有方法都将 紧密耦合 由于异常处理。因此,我们必须谨慎使用Checked Exception。 如果你开发了一个分层的企业系统,你必须选择大部分未检查的异常来抛出,但不要忘记在你什么都做不了的情况下使用检查的异常。 |
![]() |
13
1
我同意将未检查的异常作为一种规则,尤其是在设计API时。调用者始终可以选择捕获记录在案的、未经检查的异常。你只是没有不必要地强迫来电者。 我发现检查异常在较低级别很有用,作为实现细节。这似乎是一种比必须管理指定错误“返回代码”更好的控制机制。它有时也有助于看到一个想法对低级代码更改的影响。..在下游声明一个已检查的异常,看看谁需要调整。如果有很多通用的情况,最后一点不适用: catch(例外情况e) 或 抛出异常 无论如何,这通常都不是经过深思熟虑的。 |
![]() |
14
1
选中的异常对于您想向调用者提供信息的可恢复情况非常有用(即权限不足、找不到文件等)。 未经检查的异常很少(如果有的话)用于在运行时通知用户或程序员严重错误或意外情况。如果你正在编写供他人使用的代码或库,不要抛出它们,因为他们可能不希望你的软件抛出未经检查的异常,因为编译器不会强制捕获或声明它们。 |
![]() |
15
1
如果异常不太可能发生,即使在捕获到异常后我们也可以继续,并且我们无法避免该异常,那么我们可以使用检查异常。 每当我们想在发生特定异常时做一些有意义的事情,并且当该异常是预期的但不确定时,我们可以使用checked异常。 每当在不同层中导航异常时,我们不需要在每一层都捕获它,在这种情况下,我们可以使用运行时异常或将异常包装为未检查的异常。 运行时异常用于最有可能发生异常、无法进一步处理且无法恢复的情况。因此,在这种情况下,我们可以对这种例外情况采取预防措施。例如:NUllPointerException,ArrayOutofBoundsException。这些更有可能发生。在这种情况下,我们可以在编码时采取预防措施来避免此类异常。否则,我们将不得不在每个地方编写try-catch块。 更一般的例外可以设置为“未选中”,不太一般的例外则被选中。 |
![]() |
16
1
我认为我们可以从几个问题中考虑解释: 为什么会发生性行为?当它发生时,我们能做什么 一个错误,一个bug。 例如调用空对象的方法。
这种异常应在测试期间修复。否则,它会中断生产,你会得到一个非常高的bug,需要立即修复。这种例外情况不需要检查。 通过来自外部的输入, 您无法控制或信任外部服务的输出。
在这里,如果你想在名称为空时继续,你可能需要检查名称是否为空,否则,你可以不去管它,它将在这里停止,并向调用者发出运行时异常。 这种例外情况不需要检查。 由于外部的运行时异常, 您无法控制或信任外部服务。 在这里,如果你想在发生异常时继续,你可能需要捕获ExternalService的所有异常,否则,你可以不去管它,它会在这里停止,并向调用者发出运行时异常。 通过检查外部异常, 您无法控制或信任外部服务。 在这里,如果你想在发生异常时继续,你可能需要捕获ExternalService的所有异常,否则,你可以不去管它,它会在这里停止,并向调用者发出运行时异常。 在这种情况下,我们需要知道ExternalService中发生了什么样的异常吗? 这取决于:
|
![]() |
17
0
我认为在声明Application Exception时,它应该是Unchecked Exception,即RuntimeException的子类。 原因是它不会在方法上使用try-catch和throws声明来混淆应用程序代码。如果你的应用程序使用的是Java Api,它抛出了无论如何都需要处理的已检查异常。对于其他情况,应用程序可以抛出未经检查的异常。如果应用程序调用者仍然需要处理未经检查的异常,则可以完成。 |
![]() |
18
-12
我使用的规则是:永远不要使用未经检查的异常!(或者当你看不到任何绕过它的方法时) 从使用库的开发人员或使用库/应用程序的最终用户的角度来看,遇到因不可数异常而崩溃的应用程序真的很糟糕。指望包罗万象也不好。 这样,最终用户仍然可以看到错误消息,而不是应用程序完全消失。 |
|
user29759326 · 如何返回递归函数中的最后一个值? 6 月前 |
|
malife89 · 将java中的字符串读取为正确的日期格式 6 月前 |
![]() |
Tim · 在java中,有没有更快的方法将字节数组写入文件? 6 月前 |
![]() |
rudraraj · java中未声明最终变量 7 月前 |
![]() |
Bala Ji · 以下BFS的实施效率如何? 7 月前 |