Try-catch:这是可接受的做法吗?

我们收到了软件供应商提供的Java代码。 它包含很多try-catch块, catch部分没有任何内容。 他们到处都是。 例:

  try { spaceBlock.enable(LindsayModel); } catch (Exception e) { } 

我的问题是:上述可接受的做法是否合适? 如果是的话,何时? 或者我应该继续删除所有这些“虚假” trycatch语句?

对我而言,这看起来像是一种可怕的做法,但我在Java中没有足够的经验来确定。 如果你不打算对它们做任何事情,为什么要抓错? 在我看来,如果您确信exception绝对没有任何后果,并且您不关心是否发生exception,那么您只会这样做。 但是,在我们的特定应用中并非如此。

编辑提供一些背景信息:我们从供应商那里购买了一个Java脚本产品。 除产品外,他们还根据我们的需求提供了大量的概念validation脚本。 这个脚本“免费”(虽然我们不会购买产品,如果它没有附带脚本),它“工作”。 但是这个脚本是一个真正的痛苦,因为很多东西,即使我作为一个Java新手认为是可怕的做法,一个例子是这个虚假的尝试捕获业务。

这确实是一种可怕的做法。 特别是捕获Exception而不是特定的东西会散发出可怕的气味 – 甚至会吞噬NullPointerException 。 即使确保特定抛出的exception没有真正的后果,也应该始终记录它:

 try { // code } catch (MyInconsequentialException mie) { // tune level for this logger in logging config file if this is too spammy MY_LOGGER.warning("Caught an inconsequential exception.", mie); } 

但是,在这种情况下,exception不可能完全没有意义。 我建议确切地研究应用程序代码打算在这里吞下什么exception,以及它们对执行的真正意义。

一个重要的区别是try / catches是否用于吞下已检查的exception。 如果是这种情况,它可能表示对程序员非常冷漠 – 有人只是想让他/她的代码编译。 至少,代码应该修改:

 try { // code } catch (SpecificCheckedException sce) { // make sure there is exception logging done farther up throw new RuntimeException(sce); } 

这将重新抛出未经检查的RuntimeException中包含的exception,从而有效地允许代码进行编译。 即使这可以被认为是一个bandaid但是 – 检查exception的最佳实践是在当前方法中单独处理它们,或者通过向方法签名添加throws SpecificCheckedException来进一步处理它们。

正如@Tom Hawtin所提到的,可以使用new Error(sce)代替new RuntimeException(sce) ,以避免任何额外的Exception捕获更远,这对于预期不会被抛出的东西是有意义的。

如果没有使用try / catch来吞下已检查的exception,那么它同样很危险,应该简单地删除。

确实可怕。 吞下像这样的例外可能很危险。 你怎么知道发生了什么坏事?

如果供应商写评论来记录并承认它(“我们知道我们在做什么”),我会感觉更好。 如果代码中有明显的策略来处理后果,我会感觉更好。 将它包装在RuntimeException中并重新抛出; 将返回值设置为适当的值。 什么!

“到处都是”? 是否有多个try / catch块乱丢代码? 就个人而言,我不喜欢那个成语。 我更喜欢每种方法一种。

也许你应该找一个新的供应商或自己编写。

  try { meshContinuum.enable(MeshingModel); } catch (Exception e) { } 

这看起来像未完成的代码。 如果enable方法抛出exception,那么它将被代码捕获并吞没。 如果没有那么尝试捕获一个非发生的exception是没有意义的。

检查方法以及它们的签名未被throws exceptionName ,然后从它们被调用的位置删除空的try-catch语句。

理论上你可以把try-catch放在任何语句中。 编译器不会抱怨它。 它没有意义,因为这样可以隐藏真正的exception。

您可以将此视为代码质量不佳的标志。 您可能应该准备好遇到不同类型的问题。

这不是最好的:

  • 它隐藏了exception的证据,因此调试更难

  • 它可能会导致function无声地失败

  • 它表明作者可能实际上想要处理exception,但从未接触过它

因此,可能存在这样的情况,例如实际上没有任何后果的exception(想到的情况是Python的mkdirs ,如果目录已经存在则抛出exception),但通常,它不是那么好。

不幸的是你不能只删除它,因为try块会抛出一个已检查的exception,然后它必须在方法的throws子句中声明。 然后该方法的调用者必须catch它(但如果调用者也有这种catch (Exception e) {}憎恶)。

作为替代方案,请考虑将其替换为

 try { meshContinuum.enable(MeshingModel); } catch (Exception e) { throw (e instanceof RuntimeException) ? (RuntimeException) e : new RuntimeException(e); } 

由于RuntimeException(以及扩展它的类)是未经检查的exception,因此不需要在throws子句中声明它们。

您与供应商的合同有何规定? 如果他们写的,不好的做法和所有,符合规范,那么他们将收取你的重写费用。

最好指定一组测试,这些测试将输入许多或所有这些try-catch块,从而失败。 如果测试失败,你有一个更好的论据,让他们修复他们可怕的代码。

面对它的可怕想法,完全取决于你实际呼唤的是什么。 通常是出于懒惰或习惯性的不良行为。