2012-06-13 266 views
17

我听说捕捉java.lang.Error被认为是不好的做法。 我目前正在加载一个不能保证在PATH上的.dll文件,并且在不是的情况下想切换到用户配置的位置。捕捉Java错误

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

有没有更好的方法来做到这一点?或者在这里可以接受UnsatisfiedLinkError

+5

这里没有关于右对齐的信息,但是您可以在尝试...之前测试该文件是否存在... ['new File(“path/helloworld.dll”).exists()'](http:// docs。 oracle.com/javase/7/docs/api/java/io/File.html#exists%28%29)....(编辑:错误的建议,我误解了代码) –

+5

我认为这是一个可接受的解决方法。 –

+0

@Slanec你将不得不搜索'java.library.path'中的所有目录 –

回答

16

除了给出如何在技术上解决问题的建议之外,我想先花点时间解释为什么它被认为是“不好的做法”。

我们首先澄清Error类是什么。


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

有从基本Throwable类继承两个类:ExceptionError。这两个之间的区别在它们的单证解释:

错误Throwable的一个子类,表示严重 问题,合理的应用程序不应该试图捕获。大多数 这样的错误是异常的条件。 [...]

Source

异常及其子类是Throwable的指示条件的形式,合理地应用可能要 赶上。

Source


如上所述,错误和异常的,因为它们的不同来源的分离。 Error通常表示问题,其中应用程序不能从恢复。因此,他们不应该被抓到。

对于RuntimeException也是如此,但它用于指示高层图层(例如方法)的问题。 Error表示低级别问题(例如运行时)。


所以,现在你明白,你应该只捕获异常,哪些是你能够从恢复错误,回答你的问题应该是清楚的。

是的,抓住UnsatisfiedLinkError是完全合理的,因为你的应用程序可以从中恢复。


我将上述内容(更详细地以及示例)和一些扩展信息纳入article on my Blog

+0

有一次,我不得不违反这个范例,当我不得不抛出一个正常的错误,通过我从中派生出来的类没有指定任何异常。所以我从'RuntimeException'派生出了一些关于语言需求的东西。仍然希望有更好的方法来做到这一点。 – djechlin

+0

如果应用程序无法从错误中恢复,那么捕捉它并不会更坏,是吗? – simon

+0

@simon如果你真的无法从错误中恢复过来,当你抓到它时你会怎么做?如果应用程序不再工作,为什么要继续运行? –

0

loadLibrary调用findLibrary()这将是有益的,但它是受保护的,你最好的选择是写你自己的类扩展ClassLoader。类加载器有一个名为findLibrary()的受保护方法,它将返回一个库的路径,如果它不存在,则返回null。这样你可以检查null而不是捕获错误。我不确定这是否真的是“更好”,但它会消除您对试穿的需求;

+0

在检查之后和加载之前,库可能会被删除,所以try catch仍然可能是需要的。 –

0

如果您的防守编码能够从问题中恢复,那么它不是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都是为了非常糟糕的失败,无法恢复的“失败”,这真的不是即使失败,如果有一个合适的解决办法。不要让设计用来处理故障的系统过载,这相当于能够以多种方式配置系统。

0

您应该只在特定情况下捕捉错误。如果你已经探索过所有其他的可能性,只有捕获和错误。我完全同意Lukas Knuth所说的一切。但我有一个小的补充。 如果您发现任何类型的错误,请确保您尽可能缩小范围内的错误。另外,如果可能的话,确保你发现错误的方法被声明为final。原因是捕捉错误通常会导致一些非常不稳定的程序。考虑到你在一个稍后扩展来调用其他方法的方法上发生了错误,所有这些基础方法现在也会有覆盖捕获(无意)捕获的错误。

如果您需要捕捉错误,请在狭窄的控制时间内执行此操作。