捕获Java错误
我听说抓java.lang.Error
被认为是不好的做法。 我目前正在加载一个不保证在PATH上的.dll,并希望切换到用户配置的位置,如果不是。
try { System.loadLibrary("HelloWorld"); } catch(UnsatisfiedLinkError ule){ System.load("C:/libraries/HelloWorld.dll"); }
有更好的方法吗? 或者在这里捕获UnsatisfiedLinkError
可以接受?
除了就如何在技术上克服这个问题提出建议之外,我想花点时间解释为什么它首先被认为是“不良做法”。
让我们首先澄清一下Error
类是什么。
在java中,抛出错误和exception(它们是主要类型)。 使用throw
关键字完成以上操作之一。 扩展基本java.lang.Throwable
每个类都可以抛出。
有两个类inheritance自基本的Throwable
类: Exception
和Error
。 这两者之间的区别在他们的文件中解释:
Error是Throwable的子类, 表示合理的应用程序不应该尝试捕获的严重问题。 大多数此类错误都是exception情况。 […]
资源
Exception类及其子类是Throwable的一种forms,它表示合理的应用程序可能想要捕获的条件。
资源
如上所述,错误和exception因其起源不同而分开。 Error
通常表示问题, 应用程序无法从中恢复 。 因此,他们不应该被抓住。
对于RuntimeException
也是如此,但它用于指示高级别层的问题(例如方法)。 而Error
表示低级问题(例如运行时)。
所以,既然你明白你只能捕获你能够从中恢复的exception和错误,那么你的问题的答案应该是清楚的。
是的,捕获UnsatisfiedLinkError
是完全合理的,因为您的应用程序可以从中恢复。
我在上面的博客文章中介绍了上面的内容(更详细和示例)以及一些扩展信息。
您应该只在非常具体的情况下捕获错误。 如果您已经探索了所有其他可能性,那么只会发现错误。 我完全同意Lukas Knuth所说的一切。 但我有一个小的补充。 如果您发现任何类型的错误,请确保从尽可能窄的范围捕获错误。 此外,如果可能,请确保将捕获错误的方法声明为final。 原因是捕获错误通常会导致一些非常不稳定的程序。 考虑到您在稍后扩展为调用其他方法的方法上捕获错误,所有这些基础方法现在也会被覆盖的catch捕获(无意中)错误。
如果您需要捕捉错误,请在狭窄,受控制的情况下进行。
loadLibrary调用findLibrary()会有所帮助,但它受到保护,最好的办法是编写自己的类扩展ClassLoader。 类加载器有一个名为findLibrary()的受保护方法,它将返回一个库的路径,如果它不存在则返回null。 这样你就可以检查null而不是捕获错误。 我不确定这实际上是否“更好”,但它会消除你对try catch的需求;
如果您在防御性编码并且可以从问题中恢复,那么它不是Java Error
。 如果不太可能出现这样的问题,那么创建一个Exception
的子类并抛出并捕获它。 如果可能出现这样的问题,那么它甚至不应该抛出Exception
; 但是,应该是常规代码流的一部分。
try { if (config.hasCustomDLL()) { System.load(config.getCustomDLL()); } else { System.loadLibrary(Config.DEFAULT_DLL); } } catch (UnstatisfiedLinkError e) { System.out.println("Error loading DLL: " + e); }
Errors
意味着真正糟糕的故障,而不是可恢复的“故障”,如果有合适的解决方法,它们甚至都不会失败。 不要使用于处理故障的系统过载,而是能够以多种方式配置系统。