我处理过一些实例,在这些实例中,我会抛出/重新抛出异常,因为我知道围绕它的代码会捕获特定的异常。但是,是否有任何时候您想抛出异常,并且知道它不会被捕获?

或者至少,不捕获异常?

异常会立即停止应用程序,除非它们处理正确?所以我想我是在问你是否会故意让你的应用程序死掉?

有帮助吗?

解决方案

如果您的应用程序主要由其他客户端使用并且不是独立的,那么在出现您不知道如何(或不想)处理的情况时抛出异常通常是有意义的,并且没有明智的选择让你从中恢复过来的方法。客户应该能够决定如何处理您可能抛出的任何异常。

另一方面,如果您的应用程序 在端点上,抛出异常本质上成为一种通知机制,提醒人们出现了严重错误。在这种情况下,您需要考虑以下几点:

  • 应用程序的持续运行有多重要?这个错误真的无法恢复吗? 抛出异常并终止程序不是您想要在航天飞机上做的事情。

  • 您是否使用异常作为真实日志记录的代理? 几乎没有理由这样做;考虑使用真正的日志记录机制。捕获异常并让记录器弄清楚发生了什么。

  • 您想通过自己抛出异常来传达什么信息? 问问自己抛出新异常的价值是什么,并仔细考虑是否没有更好的方法来完成您想要的事情。

  • 不捕获异常可能会使资源处于不良状态。 如果你不优雅地退出,事情通常不会为你清理干净。如果您需要这样做,请确保您了解自己在做什么——如果您不打算这样做,至少考虑一下 try-finally 块,以便您可以进行一些整理。

其他提示

有就是我整个前一阵子来了一个很好的规则:

抛出一个异常时的方法不能做什么它的名字一样它。

这个想法是一个例外表明了毛病。当你实现一个方法,它是不是你的责任,以了解其是否被正确或不被使用。无论是使用方法的代码捕获异常与否不是你的责任,但使用人的责任你的方法。

遵循另一条规则是:

,除非你知道你想用它做什么,不要捕捉异常。

显然,你应该在清理代码试试... finally块,但你不应该只是捕捉异常,只是为了追赶它的缘故。你永远不应该默默地吞咽异常。虽然有些时候你可能要捕获所有异常(例如,通过做赶上(异常前)在C#),这是相当罕见的,通常有一个非常具体的技术原因。例如,当您使用.NET 2.0或更高版本使用线程,如果有异常,从你的线程逃脱,它会导致整个应用程序域卸载。在这种情况下,然而,在最起码你应该记录异常细节错误,并提供意见的说明。

一般情况下,当然也包括你的应用程序的早期迭代,不要捕获异常。通常情况下,从异常的恢复将需要某种形式的业务规则,而且,多半没有,这些业务规则不为你定义。如果你让应用死于“处理”的异常,而不是,那么你很可能会发明了业务规则,为你的客户。也不好。

捕捉每个异常只是为了追赶它着想的一般模式已经引起了我更多的麻烦比我可以指望。它通常会发生,有人把某种通用的异常处理代码在整个应用程序,这不可避免地结束了隐藏的错误或创造一些行为是不必要的。 (顺便说,捕捉和然后不重新抛出更糟。)

所以,我建议你问来代替: “?什么时候应该捕捉异常”

不确定。例如,如果你想一些字节加载到Java中的字符串:

try {
  String myString = new String(byteArray, "UTF-8");
} catch (UnsupportedEncodingException e) {
  // Platform doesn't support UTF-8?  What is this, 1991?
  throw new RuntimeExceptione(e);
}

在这种情况下,不存在适度降级,平台根本不能支持所期望的操作。您可以检查在初始化所有你想要的这个条件,但对于字符串构造仍然抛出此异常,你必须处理它。如果不是这样,也可以使用Charset.forName():)

这里的东西...它是关于“层”,或“封装”或“低耦合”。在你的代码库的某个地方,你写的方法做一些事情。说这是一个公共方法。因此,它不应该承担太多或者约来电什么...相反,它应该只是做的工作是应该做的,不管是谁喊它,什么情况下来电者是的。

如果由于某种原因,它不能完成工作,那么它需要告诉来电者:“对不起,我不能这样做,这里的原因。”例外的是一个很好的机制,让它告诉调用者(不是唯一的机制,但我见过的大多数情况下,最好的机制)。

所以,当你抛出异常,你不知道它是否会被抓住或不...因为你暴露一个公共的方法,你不知道谁可以选择调用它,这是为什么。

该异常的捕捉是“上下文”的工作。例如,假设你正在写一个库可能抛出异常的公共方法。然后,假设您正在使用该库从Windows窗体应用程序。 Windows窗体应用程序可能会捕获异常,并显示一个消息框,给用户。

但后来,你可能会使用相同的库从Windows服务。该服务会更容易捕捉异常,记录它,返回一个错误给原调用,但继续运行,因此它可以处理其他请求。

因此,例外的是像呼叫方和提供者之间的合同协议。该供应商说,“我会做任何工作或告诉你为什么我不能。你在那里做什么是你自己的事。”而来电者说,“OK,如果你不能做的工作,只是告诉我为什么,我会决定如何在这种情况下做的。”

  

但没有任何时候你想抛出一个异常,知道它不会被抓?

我要说的是,如果你手工抛出异常,大部分时间你不知道它是否会被抓住。如果你知道它会被抓住,你可能只是自己处理,而不是在第一时间抛出异常。

要说句公道话,我想部分取决于你正在做的那种节目,有时同一个程序员最终建立两个图书馆和消耗说库。

代码
  

你永远抓不住一个例外?

如果您没想到的/不知道一个例外可能会被抛出。但撇开这一边,假设你是知道的例外的,有时候你知道它在一个层级,但知道下一层起来是更合适的地方来处理它。

这取决于应用程序的类型。即使异常已经冒泡到执行上下文之后,Web 应用程序也可以继续运行。

如果您在无法处理的级别捕获异常,那么“抛出/重新抛出”异常是常见的做法。但是,您几乎总是会向问题添加上下文,至少在更高级别添加一些日志记录以表明它已被捕获并重新抛出。

例如

A调用B调用C(抛出异常)

B 接球/重投

一个接住。

在这种情况下,您可能希望 B 添加一些日志记录,以便可以区分 B 生成并引发错误,以及 C 生成并引发错误。这将使您以后能够更好地调试和解决问题。

一般来说,您几乎永远不会希望出现异常来终止您的程序。最佳实践是捕获 except 并优雅地退出。这允许您保存任何当前打开的信息并释放正在使用的资源,这样它们就不会被损坏。如果您打算退出,您可以创建自己的“核心转储”信息报告,其中包括捕获致命异常时您正在执行的操作。

如果您让异常终止您的进程,您将消除获得自定义崩溃信息的机会,并且还会跳过向用户提供友好错误消息然后退出的部分。

因此,我建议始终捕获异常,并且永远不要自愿让它们在您的程序中运行。

编辑

如果您正在编写一个库,您必须提前选择您的函数是否会抛出异常,或者是异常安全的。在这些情况下,有时您会抛出异常,并且不知道调用方是否会捕获它。但在这种情况下,只要 api 声明该函数可能抛出异常,捕获它就不是您的责任。(我正在寻找一个意思是“可能抛出异常”的词......有人知道这是什么吗?这会困扰我一整天。)

首先,有绝对有些情况下,最好是不捕捉异常。

有时,异常有时可以告诉你,你的程序是处于未知状态。有一些例外的地方,这是非常真实的本质给出的异常类型。一个NullReferenceException本质上告诉你“有一个bug”。并通过捕获这样的例外,可以隐藏的错误,这听起来在短期内好,但是从长远来看,你会更开心修复它。该产品可能不会崩溃,但它肯定不会有预期的行为。

但是,这也是我们创造我们自己的异常类型真实。有时,异常A已经抛出的事实应该是“不可能的” - 但它已经发生了,所以有一个bug

此外,当你发现一个异常很重要的事发生了:在try块(以及任何调用)内部的整个调用堆栈的finally块将被执行。什么是那些finally块呢?嗯,什么事。如果程序处于未知状态,我真的是说的任何的。他们可以从磁盘擦除有价值的客户数据。他们可能会引发更多的异常。他们可以在内存中损坏的数据,使得错误不可能诊断。

所以,当一个异常指示未知状态,你不希望运行任何代码,所以无论你做什么,的不捕获异常的。让它飞过去,和你的程序将终止无害,和Windows错误报告将能够捕捉到该程序的状态,当最初检测到的问题是。如果捕获异常,会导致更多的代码来执行,这将进一步拧了程序的状态。

其次,你应该抛出一个异常,知道它不会被抓?我认为这个问题的误解可重复使用的方法的性质。方法的整体思路是,它有一个“契约”,它如下:它接受某些参数和返回某个值,再加上它也抛出在一定条件下某些例外。这是合同 - 这是给调用者什么,他们用它做什么。对于一些来电者,意外事件可能指示恢复的情况。对于其他调用,这可能表明一个错误。从我上面说的,应该明确的是,如果一个异常指示错误,绝不能陷入的。

如果你想知道这是什么意思为微软企业库的异常处理区块的:是的,这是很破。他们告诉你catch (Exception x),然后再决定根据你的政策是否重新抛出;太晚了 - 在finally块已经由该点执行。不要做。

您可能不希望未捕获的异常任何地方的最终用户可以看到它,但它往往是可以接受的,让你的API客户端(其他程序员)决定如何处理异常。

例如,假设您正在设计一个Java类库。您揭露它接受一个String的公共方法。在应用程序中,空输入值会导致错误。代替自己处理错误,这将是可接受的,以检查空值,则抛出IllegalArgumentException。

您必须,当然,文档,你的方法抛出该异常在这种情况下的。这种行为成为你的方法的合同的一部分。

这取决于你的意思是“被抓”是什么。东西,最终某处捕获异常,无论是底层的操作系统或别的东西。

我们有一个工作流程系统,执行由各个作业的工作计划。每个作业运行的代码单元。对于一些例外,我们不希望处理它们的代码,但把它的堆栈,使外部工作流系统捕捉它(该运动员的进程之外完全发生)。

如果你正在写整个应用程序,那么你的原因是你自己的。我能想到的,你的少数情况下的可能要抛出异常,让应用程序死亡,其中大多数都不是很充分的理由,但。

最好的理由通常为调试时。我经常禁用例外,同时调试,让我更好地了解那里的东西是失败的。你也可以打开引发的异常中断在调试器,如果你与调试器中运行它的计算机上。

另一个可能的原因是持续的异常被抛出后没有意义或会导致无法挽回的可能的数据损坏或更糟(认为机器人用激光束的时候,但你应该是该死的肯定与IMO这种情况下你的应用程序了交易,崩溃程序只是懒惰的方式)。

如果你正在编写API代码或框架代码,你不会用你自己,那么你不知道,如果有人会抓住你的异常。

是啊,这是我一巴掌开发消费服务/对象,告诉他们唯一的机会“乌尔dO1n错了!!!!”。

这和摆脱,你不希望允许或看似“不可能”的可能性。即捕获所有异常并继续应用程序就是一个围墙花园的混乱所包围。

如果我需要一个中等大的系统,在某种程度上是什么,我认为是一致的方式处理数据。

沿线某处,我检测到的应用程序的状态已经变得不一致。

系统不(还)知道如何解决不一致和正常恢复

然后,是的,我会抛出与尽可能多的细节可能异常,并且会导致应用程序尽可能快地死亡,避免做任何进一步的损害的数据。如果可以回收,这将会是重要的不是有气无力地试图掩盖的混乱加剧的问题。

沿线后来有一次,导致了矛盾的事件链有了更好的理解,我更高的工具可以捕获该异常,修复状态,并继续以最小的中断。

一个库通常会抛出基于防御性编程检查异常,应的条件出现的不应该被允许通过应用程序代码出现。应用程序代码通常会被写成这样,大部分的这些无效的条件将永远不会出现,因此异常将永远不会被抛出,所以没有一点赶上他们。

根据语言(我主要是想在C方面++而不是C#,并没有说清楚的区别是什么)未捕获的异常实际抛出的效果可能是一样的东西用在做例外的前几天被发明。在C库防御编程的一个常见策略,例如,是一个错误消息立即终止该程序。

不同的是,如果异常掷确实变成是可能的(希望这将通过单元测试被发现),它常常是相对容易添加一个异常处理器可以从该问题更建设性的方式恢复。你不必重写库,或在应用程序代码中添加复杂的检查,以确保由异常投掷调用之前不能出现的情况。

我有好几个例外抛出根本没有归案。他们都是用于防御目的,而被未捕获的是不好的,做一个发生异常,这种开发和测试过程中只发生过,错误情况我没有在应用程序代码考虑那么远。而当它发生,它是不寻常的修复会很别扭 - 不需要大规模重构,无需对应用程序代码与错误条件检查,只是一个比较简单的恢复或“catch子句大规模复杂对不起,戴夫,我怕我不能这样做。”而不失效了整个应用程序。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top