java.lang.Exception与滚动你自己的exception

您将在什么时候创建自己的exception类而不是使用java.lang.Exception? (所有的时间?只有它会在包外使用?只有它必须包含高级逻辑?等等……)

我认为你需要问自己一个略有不同的问题“创建一个新的例外给我或开发人员使用我的代码有什么好处?” 它给你或其他人带来的唯一好处就是处理exception的能力。 这似乎是一个明显的答案,但事实并非如此。 您应该只处理可以合理恢复的exception。 如果您抛出的exception是一个真正致命的错误,为什么让开发人员有机会error handling它?

更深入的讨论: 自定义exception:什么时候应该创建它们?

原因一:

需要抓住具体的东西。 如果调用代码需要处理特定的exception条件,则需要区分exception,并且Java区分具有不同类型的exception,因此您需要编写自己的exception。

基本上,如果有人必须写:

catch(ExistingException e) { if({condition}) { { some stuff here} } else { { different stuff here} } } 

您可能想要编写特定的扩展名; catchexception匹配比条件更清晰,恕我直言。

请记住:您的新Exception 可以是 RuntimeException的子类

原因二:

API整合。 如果你编写一个接口并且你有几个实现,那么它们可能会调用不同的API,抛出一大堆不同的非RuntimeExceptions:

 interface MyInterface { void methodA(); } class MyImplA { void methodA() throws SQLException { ... } } class MyImplB { void methodA() throws IOException { ... } } 

你真的希望MyInterface.methodA抛出SQLException和IOException吗? 也许那么在自定义exception中包装可能的exception是有意义的。 这也可以是RuntimeException。 甚至RuntimeException本身……

我相信:

 catch (Exception e) { ... } 

……是一个应该避免的反模式。 您可能希望在应用程序的某个位置使用一个集中的广泛捕获,以记录错误并防止整个应用程序终止 – 但将它们分散在willy-nilly周围是不好的。

为什么:

 try { if(myShape.isHidden()) { throw new Exception(); } // More logic } catch (Exception e) { MyApp.notify("Can't munge a hidden shape"); } 

所以你试试这个,由于编码错误,myShape为空。 当运行时试图取消对myShape的拒绝时,会抛出NullPointerException。 当应该报告空指针时,此代码报告隐藏的形状。

要么做出自己的exception,要么在API中找到适当的专门exception。 它不像扩展Exception或RuntimeException是繁重的。

当我想以不同于其他人的方式对待我的例外时。 如果我想抓住我的并传播其他所有人,或者如果我想抓住其他人并传播我的,或者如果我想抓住两者但是以不同方式对待它们,那么我将为我的exception定义一个单独的类。 如果我想对它们进行相同的处理,无论是通过传播它们还是通过捕获它们(并且使用捕获的exception以任何方式做同样的事情),我将使用标准类。

如果存在语言运行库或库的现有exception,请使用它ELSE创建自己的,文档很好,并且应该在99%的情况下工作。

软件捕获意义。

抛出现有exception几乎没有理由:JVM已经为您做到了。 您的exception版本不是很准确,抛出“exception”也没有意义。

由于您编写的解析算法,您可能会遇到DataFormatException 。 然而,这种情况很少见。

当您的程序遇到exception情况时,它几乎总是独一无二的程序。 为什么要将您的exception情况强制适应现有的exception? 如果它对你的程序来说是独一无二的,那么……好吧……它是独一无二的。 这样命名。

但是,不要为每个唯一消息提供唯一的exception类。 一个exception可以包含许多变体消息和支持细节。

翻译为Java的Python经验法则是在包级别定义任何唯一的exception。 [在Python中,他们建议在“模块”级别使用exception,这些exception并不能精确地转换为Java。]

始终使用常见的exception类启动,然后当需要特别处理它时,更改它。

  1. 在第一次创建方法时,只需让exception通过即可。

  2. 如果存在必须处理的exception,那些可以在throws中定义,也可以包装到某些运行时exception或者包装自己的throwsexception。 在许多情况下我更喜欢运行时exception。 从API的角度来看,应该避免定义抛出定义,直到需要它为止。

  3. 稍后当需要在某些调用者中对exception进行特定处理时,请返回并为其创建新的exception。

关键是要在知道需要之前避免做额外的工作。

如果某个对象/类/方法有问题,我无法想象特定地抛出java.lang.Exception。 它太通用了 – 如果你不打算创建自己的Exception类,在我看来应该至少在API中有一个更具体的Exception类型。

当exception与API相关时,我会使用Java API中的exception。 但是如果出现了我自己的API独有的exception情况,那么我将为它创建一个Exception。 例如,如果我有一个Range对象,其中包含两个属性min和max以及不变min <= max,那么我将创建一个异常InvalidRangeException。

当我编写代码时,这会有所帮助,因为我知道exception的来源是因为我违反了我自己的条件之一或来自Java API的东西。

在大多数情况下,创建自己的exception类没有意义。

新手程序员有一种倾向,就是创建自己的exception类,这样他们就可以使用更能说明错误类型的名称。 因此,您将找到类似FTPInitializationException,DAOFactoryException等的类,即使这些exception的处理方式与标准exception不同。 这显然是应该避免的反模式。