放松异常捕获必要性

时间:2011-04-25 13:22:07

标签: java checked-exceptions

Java是否有可能摆脱捕获非RuntimeException异常的必要性?也许编译器标志?

我知道捕获被提升的原因,但是想要做简单直接的工具来强制执行他们的要求。因此,如果出现问题,我不想赶上但退出应用程序,崩溃时会出现一个有意义的异常。通常这最终会像:

try {
     connection.close();
} catch (IOException e) {
    throw new RuntimeException(e);
}   

引入了4行代码混乱,并在错误输出上引入了包装RuntimeException混乱。有时它甚至会激励人们围绕任何东西包裹大try ... catch (Throwable ..)块,这可能是我们心爱的'未知错误发生'警告框的原因......

6 个答案:

答案 0 :(得分:3)

您可以在方法原型中使用throws关键字来避免try-catch阻止。最终会将异常抛出到JVM的Default Exception处理程序,如果在代码中没有指定catch块来处理引发的异常,它会暂停应用程序。

答案 1 :(得分:3)

在第一眼看到异常时崩溃应用程序是非常不良做法。特别是当某些工作未保存且应用程序正在使用某些资源时,需要在应用程序终止执行之前被释放和清理。一些非常流行的软件用来做到这一点......而不是“修复”这个问题,他们在应用程序重启时引入了数据可恢复性功能。不过这个诀窍,这不是好的软件工程。

至少,您的应用程序不应在遇到的第一个异常/错误时崩溃,而是使用有意义的消息进行恢复。将所有内容包装在RuntimeException(或甚至Throwable)中是懒惰的,尤其是不对它做任何事情。

Java不支持任何类型的标志,因为有1)解决方法,2)更好的方法来处理这种情况。例如:

<强> 1。处理调用方法中的异常

您可以在方法声明中添加throws关键字,直到您的static public void main方法,如果不处理异常,最终会使堆栈跟踪崩溃。

class Foo {
   public void someMethod(....) throws IllegalArgumentException, IOException {
      ...
   }

   static public void main(String...args) throws Throwable {
      new Foo().someMethod();
   } 
}

此方法不提供任何可恢复性方法,并且可能会使您的用户不满意(如果他们从控制台运行应用程序,则会出现一个无意义的无意义的stachtrace,或者如果他们从快捷方式或GUI启动应用程序则根本没有任何内容)。此外,如果您有一些获得的资源,则在发生异常时您将无法清除它们。至少,您的main应该catch (Throwable e)并在抛出上述异常之前输出一些内容。类似的东西:

class Foo {
   public void someMethod(....) throws IllegalArgumentException, IOException {
      ...
   }

   static public void main(String...args) {
      try {
         new Foo().someMethod();
      } catch (...) {
         // output or log exception here and, optionally, cleanup and exit
      }
   } 
}

** 编辑 **

考虑这种情况:程序正在初始化某些资源以处理某些数据,然后在处理期间发生一些运行时异常(或错误),应用程序崩溃,但资源未被释放或释放。但是,在Java中,可以做到这一点

public E doSomething() throws RuntimeException {
   // declare a bunch of resources

   try {
      // process resources with unchecked exceptions
   } finally {
      // free resources
   }

   // return some result
}

并在出错或成功时彻底退出方法,甚至可能记录“后代”的运行时错误。

<强> 2。记录错误并返回一些有意义的值

记录是一种非常好的做法。您可以向用户显示一些消息,告诉他们在不崩溃整个事情的情况下无法执行操作,并向您提供用户执行操作的内容和位置的一些跟踪。简单的日志记录系统可能是:

class Foo {
   static private final Logger LOG = Logger.getLogger(Foo.class.getName());

   public boolean doSomethingImpl(...) {
      boolean result = true;
      try {
        ...
      } catch (SomeException e) {
         LOG.log(Level.SEVERE, "meaningful message why method could not do something!", e);
         result = false;
      }
      return result;
   }

   public void doSomething() {
      if (!doSomethingImpl(...)) {
          // handle failure here
      }
   }
}

默认情况下,Logger会将所有内容输出到err输出流,但您可以添加自己的处理程序:

// loggers are singletons, so you can retrieve any logger at anytime from
// anywhere, as long as you know the logger's name
Logger logger = Logger.getLogger(Foo.class.getName());

logger.setUseParentHandlers(false);  // disable output to err
logger.addHandler(new MyHandler());  // MyHandler extends java.util.logging.Handler

Java已经附带了一些默认的日志记录处理程序,其中一个是writes to file

答案 2 :(得分:1)

我认为JVM没有任何办法解决这个问题。你最好的办法是让你的方法重新抛出异常,从而消除你代码中的“混乱”,然后让你的主程序抛出异常。这应该将错误传播到程序的顶部。

但请记住,异常实际发生的地方是让用户知道发生了什么的更好的地方(也就是说,当这个特定的IOException发生时它正是在做什么)。如果所有错误都简单地传播到最高级别,您将失去此解决方案。

答案 3 :(得分:1)

您可以将异常提升到一个级别。这是一个例子

public class Foo {
    public Foo() {
        super();
    }
    public void disconnect(connection) throws IOException {
        connection.close();
    }
}

答案 4 :(得分:1)

使用“投掷”来避免错误..但这不是一个好的编程习惯

答案 5 :(得分:1)

  

Java是否有可能摆脱捕获非RuntimeException异常的必要性?

对于已检查的异常,您可以选择捕获异常并在方法标题中将其声明为抛出。

  

也许是编译器标志?

没有。没有编译器标志来放松这个。它是语言设计的基础部分。通过编译器开关放宽已检查的异常规则会导致严重的库互操作性问题。

相关问题