捕获Java错误

捕获Java错误,java,error-handling,Java,Error Handling,我听说捕获java.lang.Error被认为是不好的做法。 我当前正在加载一个不保证在路径上的.dll,如果它不在路径上,我希望切换到用户配置的位置 try { System.loadLibrary("HelloWorld"); } catch(UnsatisfiedLinkError ule){ System.load("C:/libraries/HelloWorld.dll"); } 有更好的方法吗?或者捕获此处的未满足链接错误是否可以接受?loadLibrary调用fi

我听说捕获
java.lang.Error
被认为是不好的做法。 我当前正在加载一个不保证在路径上的.dll,如果它不在路径上,我希望切换到用户配置的位置

try {
    System.loadLibrary("HelloWorld");
} catch(UnsatisfiedLinkError ule){
    System.load("C:/libraries/HelloWorld.dll");
}

有更好的方法吗?或者捕获此处的
未满足链接错误
是否可以接受?

loadLibrary调用findLibrary(),这会很有帮助,但受到保护,最好的办法是编写自己的类扩展类加载器。类加载器有一个名为findLibrary()的受保护方法,该方法将返回库的路径,如果不存在,则返回null。这样,您就可以只检查null而不是捕获错误。我不确定这是否真的“更好”,但它将消除你的尝试捕捉的需要

除了就如何从技术上解决这个问题提供建议之外,我想花点时间解释一下为什么它首先被认为是“坏习惯”

让我们从澄清
错误
类是什么开始


在java中,抛出错误和异常(这是主要类型)。通过使用
throw
关键字来抛出上面的一项。每个扩展基本
java.lang.Throwable
的类都可以抛出

有两个类继承自基本的
Throwable
类:
Exception
Error
。这两者之间的差异在其文档中进行了解释:

错误是Throwable的一个子类,表示严重错误 合理应用程序不应试图捕捉的问题。最 此类错误属于异常情况。[…]

类异常及其子类是可丢弃的一种形式 表示合理的应用程序可能需要的条件 接住。


如上所述,错误和异常是分开的,因为它们的起源不同。
错误
通常表示应用程序无法恢复的问题。因此,他们不应该被抓住

对于
运行时异常
也是如此,但它用于指示高级层(例如方法)存在问题。而
错误
表示低级问题(例如运行时)


因此,现在您已经了解到,您应该只捕获能够从中恢复的异常和错误,您的问题的答案应该是清楚的

是的,捕获
未满足的链接错误是完全合理的,因为您的应用程序可以从中恢复



我在一篇文章中介绍了上述内容(更详细,并附有示例)和一些扩展信息。

如果您是防御性编码,并且可以从问题中恢复,那么这不是Java
错误。如果这样的问题不太可能发生,那么创建
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);
}

错误
是指非常严重的故障,不可恢复的“故障”,如果有合适的解决方法,这些故障甚至不是故障。不要让设计用于处理故障的系统过载,因为这相当于能够以多种方式配置系统。

您应该只在非常特定的情况下捕获错误。只有在你探索了所有其他可能性的情况下,才能抓住错误。我完全同意卢卡斯·克努斯所说的一切。但我有一个小补充。 如果您想要捕获任何类型的错误,请确保捕获范围尽可能窄的错误。另外,如果可能的话,确保捕获错误的方法声明为final。原因是捕捉错误通常会导致一些非常不稳定的程序。考虑到在稍后扩展到调用其他方法的方法中捕获错误,所有这些底层方法现在也会有错误(由catch)捕获(无意)。


如果您需要捕捉错误,请以一种狭窄、可控的方式进行

不知道这里的正确转换,但您可以在尝试之前测试文件是否存在。。。。(编辑:错误的建议,我误读代码)我认为它是一个可接受的解决方案。@ SLANEC你必须搜索所有的目录在<代码> java .Labor。路径< /代码>我猜在这种情况下它的OK。虽然您可以事先测试文件是否存在。。。但这并没有那么有趣,因为你必须手动搜索整个路径……我看不出有什么问题。有一次我不得不违反这个范例,那就是我必须通过一个没有指定任何异常的类抛出一个正常错误。因此,我从
RuntimeException
派生出了语言需求。仍然希望有更好的方法来做到这一点。如果应用程序无法从错误中恢复,那么捕获错误的情况也不会更糟,是吗?@simon如果你真的无法从错误中恢复,当你捕获错误时,你会怎么做?如果应用程序不再工作,为什么要让它继续运行?库可能在检查之后和加载之前被删除,因此可能仍然需要try-catch。