为什么抛出自己的异常是一个“坏主意”?
10 回答
一般来说,抛出你自己的异常是完全可以的。也许您要问的是“什么时候抛出我自己的异常不一定是个好主意?”
一种情况是您应该抛出标准异常。例如,如果您的方法采用文件名并且应该返回一个文件,您可能应该抛出您平台的标准 FileNotFoundException 而不是抛出 PeanutPowersFileNotFoundException。如果你真的想抛出你自己的异常,你可能应该让它扩展标准的 FileNotFoundException。
更新: Bloch 在Effective Java的第 60 条中解释了这一点
它不是。每当遇到异常情况时,您都应该创建并抛出自定义异常。
不提供它们派生自任何标准基本异常类型(c++ 中的 std::exception 或 python 中的 Exception 等...)
如果它们不是从正常的基本类型派生的,那么其他人在期望捕获所有异常时可能无法捕获它们——这将是一件坏事。
创建自己的异常类型并没有错。但是,在创建自己的框架之前,您应该检查您的框架是否已经提供了适合的异常。
来自.Net 设计指南:
考虑抛出驻留在系统命名空间中的现有异常,而不是创建自定义异常类型。
如果您有一个可以以不同于任何其他现有异常的方式以编程方式处理的错误条件,请创建并抛出自定义异常。否则,抛出现有异常之一。
不要为了让你的团队例外而创建和抛出新的例外。
我相信您可能会问为什么重新抛出异常是一个坏主意。
通过“重新抛出”,我的意思是捕获一个异常,而不是生成一个新异常并抛出它。这可能是有问题的,因为您最终可能会消耗原始堆栈跟踪并丢失错误的所有上下文。
你不应该发明自己的异常类型,除非你有一些额外的东西要添加到异常类型中。
如果你想告诉 API 的用户他们提供了一个无效的参数,你应该抛出一个 ArgumentException,但是如果你的库由于某些库特定的原因而失败,你不能在常规异常中传达,你应该滚动你自己的,让它包含开发人员需要的信息。
继续 Peter 的回答,另一个在抛出异常时不是一个好主意的情况是,如果您使用抛出异常来控制程序的业务逻辑。
只要您抛出的异常是从适当的对象派生的,并且只是传达了这一点——异常情况,抛出异常是完全可以接受的。
除了作为一种糟糕的设计模式之外,使用抛出异常来控制业务逻辑还具有性能影响 - 与基于从方法返回的结果进行分支相比,抛出和捕获异常相当昂贵
创建自己的异常并没有错,可以对其进行定制以准确传达适合您情况的信息。AConfigFileNotFoundException
比 a 传达更多信息FileNotFoundException
(我们没有找到哪个文件?)。
但是,无论如何,请确保您捕获并处理代码中的每个自定义异常。当异常飞到你的模块之外的某个地方(称之为包,称之为命名空间)时,那些人甚至不会知道它的存在,更不用说如何处理它了。除了一个.catch (Throwable t) {/* whut? */}
对我来说,问题似乎是抓住没有经验的候选人试图伪造经验。在我看来,抛出自己的异常并没有错,正如您在这里回答的其他所有人看到的那样。
这根本不是一个坏主意。如果出现异常情况,应该抛出异常来处理它,特别是如果您正在设计其他人可能使用的代码,可能会收到错误的输入等。
在不是绝对必要的情况下使用异常是一个坏主意,例如可以通过代码中的正常检查或作为正常执行的一部分来恢复的情况,因为它们确实有很多与之相关的开销。我想这就是您可能会认为它们通常是个坏主意的地方。但是对于它们的意图(标记您的代码无法处理的异常情况),它们绝对是最好的工具。
如果您确实为其他人可能使用的代码创建了自定义异常,请记录它们是什么以及它们的含义。这样,您的代码的以后用户将知道它们是可能的以及它们出现时的含义,并且可以适当地处理它们。