处理构造函数中抛出的致命异常

时间:2011-03-11 15:34:24

标签: java exception

假设我有一个类需要在其构造函数中进行一些初始化工作。没有理由相信它会失败,但如果确实如此,那么实例(可能是应用程序;让我们认为这些是两个独立的情况)将处于无法使用的状态,并且在该范围内没有真正的恢复希望(实例或全球)。

在Java中处理这种情况的推荐方法是什么?重新抛出异常,包含在运行时异常中,似乎是一种自然的方法,但对于为此目的使用哪种异常类型是否有任何建议或共识?

4 个答案:

答案 0 :(得分:1)

如果构造函数中的某些内容抛出异常,您可以声明它自己抛出异常,也可以用更常见的异常包装它们(比如自己的InstantiateXxxxException)。

通常,您有多种类型的Throwable具有不同的含义 我将它们分类如下:

  • 异常(已检查):当状态可恢复或需要其他处理时抛出
  • RuntimeException(未选中):当意外异常(如NPE)发生时,应用程序可能仍处于稳定状态,取决于处理和情况。一些框架(如EJB)将每个异常包装到RuntimeException(或更常见的子类)中,以便创建一个“更清晰”的接口。
  • 错误(未经检查):当发生极其糟糕的事情时会抛出这种情况,这会破坏应用程序甚至JVM(如OutOfMemoryError)的稳定性。在这种情况下,应用程序通常会退出,尽管您可能想要捕获它们并在可能的情况下进行一些特殊处理(例如写日志等)。

答案 1 :(得分:0)

这取决于出了什么问题。我的意思是如果由于null值而失败,那么NullPointerexception,如果你遇到了不期望的状态,那么可能是IllegalStateException。

但我建议不要暴露构造函数只是有一个静态工厂方法,你可以命名,并可以优雅地处理这种情况。 e.g。

public class A{
  private A() {}

  private init() { .. }

   public static A getNewInstance() { //  may be parameters if you want
      A a = new A();
      a.init();
  }
}

我刚刚举了一个init的例子,但你也可以有其他的选择,重点是你可以使用静态方法来处理这些东西而不是构造函数,如果构造函数正在处理复杂的逻辑。

答案 2 :(得分:0)

如果在对象的构造函数中抛出异常,它与在方法调用中查找异常没什么不同,除了可以保证对象没有被构造

NewObject obj = null;
try {
   obj = new NewObject() {
} catch (Throwable t) {
   // obj is null.
}

是否可以从这样的异常中恢复很大程度上取决于抛出的异常。预计会检查异常,但偶尔会出现错误;通常他们是最容易恢复的。未经检查的异常涉及除以零之类的事情(必须捕获每个可能的抛出将是繁琐的)。错误是程序可能因正常JVM操作未保持的标准假设而失败的情况(如分配更多内存的能力)。

可以从某些JVM错误中恢复;但是,您希望从中恢复的错误以及恢复方法需要仔细规划。通常,人们会看到在处理内存不足的情况时尝试从JVM错误中恢复(后面是伪Java代码)

Runtime runtime = Runtime.getRuntime();
while (true) {
  Cache myCache = new SomeCache();
  try {
    Message message = messages.getMessage();
    if (!(cache.hasKey(message))) {
      Result result = messageProcessor.getResult(message);
      cache.put(message, result);
    }
    message.getReplyChannel().send(cache.get(message));
  } catch (OutOfMemoryException e) {
    myCache.clear();
    runtime.gc();
    messages.putBack(message);
  }
}

这种解决方案的价值在很大程度上取决于系统设计的其余部分。假设“缓存”具有有限的最大大小,如果程序的另一部分开始占用内存,这可能仍然有用。关键是要确保你的内存释放操作依赖于已经分配的对象,这些对象在尝试释放内存时不会对系统产生更多的内存需求。

答案 3 :(得分:-1)

如果整个应用程序处于不稳定状态,我建议直接退出应用程序以避免更多问题。只需在system.err之前输出一些内容。

如果只有实例处于不稳定状态,你可以抛出运行时异常,但我认为这是一种危险的方式,因为它们没有义务捕获异常,这可能会导致以后出现一些问题。

我建议简单地重新抛出异常,或者用其他相关信息将其包装在另一个异常中。异常的确切类型将在很大程度上取决于案例(空指针,非法状态,错误等)