我们已收到软件供应商提供的Java代码。它包含许多try-catch
块,catch
部分没有任何内容。他们到处都是。例如:
try {
spaceBlock.enable(LindsayModel);
} catch (Exception e) {
}
我的问题是:上述可接受的做法是否合适?如果是的话,何时?或者我应该继续删除所有这些“虚假”try
和catch
声明?
对我而言,这看起来像是一种糟糕的做法,但我在Java中没有足够的经验来确定。如果你不打算对它们做任何事情,为什么要抓错?在我看来,如果您确信异常绝对没有任何后果,并且您不关心是否发生异常,那么您只会这样做。但是,在我们的特定应用中并非如此。
编辑提供一些背景信息:我们从供应商那里购买了一个Java脚本产品。除产品外,他们还根据我们的需求提供了大量的概念验证脚本。这个脚本是“免费的”(虽然我们不会购买产品,如果它没有附带脚本),它“工作”。但是这个剧本真的很难建立起来,因为很多事情甚至我作为Java新手都认为是糟糕的做法,其中一个例子就是这种虚假的尝试捕捉业务。
答案 0 :(得分:19)
这确实是一种可怕的做法。特别是捕捉Exception
而非特定的东西会散发出难闻的气味 - 即使是NullPointerException
也会被吞噬。即使确保特定抛出的异常没有真正的后果,也应该始终记录它:
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);
}
然而,在这种情况下,异常不可能完全没有意义。我建议准确研究应用程序代码在这里想要接受的异常,以及它们对执行的真正含义。
一个重要的区别是try / catches是否用于吞下已检查的异常。如果是这种情况,它可能表示对程序员非常冷漠 - 有人只是想让他/她的代码编译。至少,代码应该修改:
try {
// code
}
catch (SpecificCheckedException sce) {
// make sure there is exception logging done farther up
throw new RuntimeException(sce);
}
这将重新抛出未经检查的RuntimeException
中包含的异常,从而有效地允许代码进行编译。即使这可以被认为是一个绑定但是 - 检查异常的最佳做法是在当前方法中单独处理它们,或者通过向方法签名添加throws SpecificCheckedException
来进一步处理它们。
如上所述@Tom Hawtin,可以使用new Error(sce)
代替new RuntimeException(sce)
,以避免任何额外的Exception
捕获更远,这对于不是预计会被抛出。
如果没有使用try / catch来吞下已检查的异常,那么它同样危险,应该被删除。
答案 1 :(得分:8)
如果供应商写评论来记录并承认它(“我们知道我们在做什么”),我会感觉更好。如果在代码中有明显的策略来处理后果,我会感觉更好。将它包装在RuntimeException中并重新抛出;将返回值设置为适当的值。什么!
“到处都是”?是否有多个try / catch块乱丢代码?就个人而言,我不喜欢那个成语。我更喜欢每种方法一种。
也许你应该找一个新的供应商或自己编写。
答案 2 :(得分:2)
try {
meshContinuum.enable(MeshingModel);
} catch (Exception e) {
}
这看起来像未完成的代码。如果enable方法抛出异常,那么它将被代码捕获并吞没。如果没有,则尝试捕获非发生的异常是没有意义的。
检查方法以及throws exceptionName
未遵循其签名的位置,然后从调用它们的位置删除空的try-catch语句。
理论上你可以把try-catch放在任何语句中。编译器不会抱怨它。但这没有意义,因为这样可以隐藏真正的异常。
您可以将此视为代码质量不佳的标志。您可能应该准备好遇到不同类型的问题。
答案 3 :(得分:1)
这不是最好的:
它隐藏了异常的证据,因此调试更难
可能会导致功能无声地失败
这表明作者可能实际上想要处理异常,但从未接触过它
因此,可能存在这样的情况,例如实际上没有任何后果的异常(想到的情况是Python的mkdirs
,如果目录已经存在则抛出异常),但通常,它不是那么好。
答案 4 :(得分:1)
不幸的是你不能只删除它,因为try块会抛出一个已检查的异常,然后它必须在方法的throws
子句中声明。然后,该方法的调用者必须catch
(但如果调用者也有catch (Exception e) {}
憎恶,则不会这样做)。
作为替代方案,请考虑将其替换为
try {
meshContinuum.enable(MeshingModel);
} catch (Exception e) {
throw (e instanceof RuntimeException) ? (RuntimeException) e : new RuntimeException(e);
}
由于RuntimeException(以及扩展它的类)是未经检查的异常,因此不需要在throws子句中声明它们。
答案 5 :(得分:1)
您与供应商的合同有何规定?如果他们所写的内容,不良做法以及所有内容符合规范,那么他们会向您收取重写费用。
最好指定一组测试,这些测试将输入许多或所有这些try-catch块,从而失败。如果测试失败,你有一个更好的论据,让他们修复他们可怕的代码。
答案 6 :(得分:0)
面对它的可怕想法,完全取决于你实际上在呼唤什么。通常是出于懒惰或习惯性的不良行为。
答案 7 :(得分:0)
实际上...不是很快。
在某些情况下,可以忽略异常。
try {
something-that-throws();
} catch(Exception e) {
try {
something-else-that-throws();
} catch(Exception e1) {}
throw e;
}
if (reinitialize) {
try {
FileUtils.forceDelete(sandboxFile); // delete directory if it's there
} catch(Exception e) {}
}
上面的代码保存了一个相当折磨的尝试,可以在删除沙箱文件之前查看它是否确实存在。