简体   繁体   中英

How to avoid try-catch statement in methods?

It seems for me personally (It doesn't mean that I'm right or something), that including try-catch statement in methods 'overloading' their inner structure for a reader. When working with a DB you should include such thing as SQLExceptions, ConnectionExceptions, maybe more. Is there any way to put responsibility for ALL Exceptions on some ONE object?

I thought something like that:

enum TaskEnum {
    doSmth1, doSmth2, doSmth3, doSmth4
}

class OuterClass {

    doWhatever(TaskEnum task, String… args) {
        try {
        switch(task) {
                case (doSmth1): InnerClassInstance.execute1(args); break;
                case (doSmth2): InnerClassInstance.execute2(args);break;
                case (doSmth3): InnerClassInstance.execute3(args);break;
                case (doSmth4): InnerClassInstance.execute4(args);break;

        } catch(Exception e) {
                 e.printStack()}
         }
     }
}

class InnerClass {    
    execute1(String args) throws Exception() {bla-bla-bla};
    execute2(String args)throws Exception() { bla-bla-bla };
    execute3(String args)throws Exception() { bla-bla-bla };
    execute4(String args)throws Exception() { bla-bla-bla };
}

In that way Outer class will be responsible for Exceptions thrown by all his inner class methods. Of course, I wouldn't asked this question, if considered my solution a GOOD one. It's just an example, for you to understand the idea.

Please, share your thoughts about this.

The beauty of the exception mechanism is not having to deal with them where they occur, but at a common place, grouping together the handling of many possible failures. So yes, definitely postpone the handling of exceptions until a convenient moment. There are two main choices:

  1. Failures that must abort the current unit of work: handle them all at the level which encompasses the entire transaction scope, and do it uniformly (typically a log entry and an error message to the upstream client);

  2. exceptions that only imply alternative program flow within a unit of work: these are good candidates for checked exceptions as they must be handled specifically and early. Don't log these at error level (it could be a warning or just info, depending on context).

Unfortunately, Java's checked exceptions make the first option harder to implement since every method on the way must declare all checked exceptions that it may throw. There are also some common pitfalls: Eclipse and other tools offer to surround your code with a boilerplate try-catch, where instead you should have let the exception propagate upwards. A particularly difficult situation arises when you are implementing a method that doesn't declare the checked exception you are encountering, forcing you to handle it too early. In such cases one must wrap the checked exception into RuntimeException and rethrow it. This is quite non-obvious and causes many bugs, or at least duplicated error log entries.

There are two options that are commonly used, pretty much as you said. Either deal with exceptions where they arise, or have lower level methods throw the errors themselves until it gets to a top level class that deals with all Exceptions. I personally feel that Exceptions should be dealt with where they are thrown and they should be as specific as possible. I'm not a fan of the second option because it puts too much responsibility on the top level class. It's really your preference though, and of course you should only deal with the exception when it is convenient and makes sense to do so.

I still don't get what you are trying to do. A catch block that just prints a stack trace is IMHO more than useless. And providing a task enum just to switch on its values like that doesn't make sense to me. If you want to go down that path, use what Java has to offer:

enum TaskEnum {
    doSmth1() {
        public void execute(String... args) {
            // blablabla
        }
    },
    doSmth2() {
        public void execute(String... args) {
            // blablabla
        }
    };

    public abstract void execute(String... args);
};

class OuterClass {

    public void doWhatever(TaskEnum task, String... args) {
        try {
            task.execute(args);
        } catch (Exception e) {
            e.printStackTrace();
            // and do something useful!
        }
    }

}

But it would be even better to either not catch the exceptions at all, or wrap them in another exception class if needed (ie when a super class imposes restrictions on the exceptions thrown).

throws cannot be used at the class level, only the method level.

You could do:

public void method() throws IOException {

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM