开发者

relax exception catch necessity

开发者 https://www.devze.com 2023-02-28 07:41 出处:网络
Is the开发者_JS百科re a possibility in Java to get rid of the necessity to catch non-RuntimeException exceptions? Maybe compiler flags?

Is the开发者_JS百科re a possibility in Java to get rid of the necessity to catch non-RuntimeException exceptions? Maybe compiler flags?

I know the reason why the catching is promoted, but want to do simple and straight tools that enforce their requirements. So if something can went wrong I don't like to catch up but exit the application, crashing with a meaningful exception. Usually this ends up like:

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

which introduces 4 lines of code mess, and introduces the wrapping RuntimeException mess on error output. Sometimes it even motivate people to wrap large try ... catch (Throwable ..) blocks around anything, which is the likely cause for our beloved 'Unknown error occured' alert boxes...


you can use throws keyword with method prototype to avoid try-catch block. which eventually throws the exception to JVM's Default Exception handler which halts the application if no catch block's are specified in your code to handle the exception raised.


Crashing the application at the first sight of an exception is very bad practice. Especially when some work is unsaved and the application is using some resources that needs to be freed and cleaned before the application terminates execution. Some very popular software used to do that... and instead of "fixing" the issue, they introduced a data recoverability features on application restart. However the trick, this is not good software engineering.

At the very least, your application should not crash on the first exception/error encountered, but recover with a meaningful message. It is being lazy to just wrap everything in a RuntimeException (or even Throwable) and, especially, not do anything with it.

Java does not support flags of any kind because there are 1) a workaround, and 2) better ways to handle this situation. For example :

1. Handle the exception in the calling method

You can add the throws keyword in your method declaration, up to your static public void main method, which, if not handling the exception, will eventually crash the application with a stacktrace.

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

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

This method does not offer any means of recoverability and will probably make your user unhappy (with a big meaningless stachtrace if they ran the application from a console, or just nothing at all if they launched it from a shortcut or GUI). Also, if you have some acquired resources, you will not be able to clean them when an exception occurs. At the very least, your main should catch (Throwable e) and output something before throwing the exception above. Something like :

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
      }
   } 
}

** EDIT **

Consider this scenario : a program is initializing some resource for processing some data, then some runtime exception (or error) occurs during processing, the application crash, but the resources are not released or freed. In Java, however, one could do this

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

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

   // return some result
}

and cleanly exit the method on error or on success, perhaps even logging the runtime error for "posterity".

2. Log the error and return some meaningful value

Logging is a very good practice. You can show your user some message telling them that the operation could not be executed without crashing the whole thing, and giving you some traces of what and where the user were doing. A simplistic logging system could be :

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
      }
   }
}

By default, the Logger will output everything to the err output stream, but you can add your own handlers :

// 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 already ships with some default logging handlers, one of which writes to file.

etc.


Is there a possibility in Java to get rid of the necessity to catch non-RuntimeException exceptions?

For a checked exception, you can chose between catching the exception and declaring it in the method header as thrown.

Maybe compiler flags?

No. There are no compiler flags to relax this. It is a fundamental part of the language design. Relaxing the checked exception rules via a compiler switch would cause serious library interoperability problems.


I don't think that there's any way around this for the JVM. Your best bet is to have your methods re-throw the exception, which gets rid of the "mess" in your code, and then have your main program throw Exception. This should propagate the error up to the top of your program.

Keep in mind, however, that the place where the exception actually happens is a much better place to let the user know what happened (i.e., exactly what it was doing when this particular IOException happened). You'll lose this resolution if all errors are simply propagated up to the top level.


You do have the ability to throw your exceptions up a level. Here's an example

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


Use "Throws" to avoid the error..but it will not be good programimg practice

0

精彩评论

暂无评论...
验证码 换一张
取 消