I read in a C# introductory book that you shouldn't catch an exception if you don't know what to do with it. Thinking of that bit of advice while programming in Java, I sometimes find I do not know what to do with an exception, but I am forced to catch it or "percolate it up" to avoid a compile error. I'd rather not clutter methods with throws clauses all the way up the call tree so I have often resorted to "converting" the exception to a RuntimeException as in the following. Adding throws clauses to many methods for an exception that isn't really "handled" (properly dealt with) seems verbose and distracting. Is the following bad style and if so what is a better way to deal with this?

try {
  thread.join();
}
catch (InterruptedException e) {
      Console.printwriter.format("%s\n", e.printStackTrace());
  throw new RuntimeException();
}

Edit: Aside from the clutter, there's another problem with the percolating exceptions: after code revisions you probably end up with some unnecessary throws clauses. The only way I know to clean them out is by trial and error: remove them and see if the compiler complains. Obviously, this is annoying if you like to keep the code clean.

有帮助吗?

解决方案

The division in Java between checked and unchecked exceptions is somewhat controversial.

If you control the interface, adding a throws clause to the signature is usually the best way.

If you are in a situation where you cannot deal with an exception, but are not allowed to let it bubble up because of the checked exception signature, then wrapping the exception into an exception that you can rethrow (often a RuntimeException) is common practice.

In many cases, you'd want to use another checked exception, though, such as IOException or SQLException. But that is not always an option.

But in your example, include the original exception as the "cause":

 throw new RuntimeException(e);

This may also remove the need for the logging (because this can also be deferred to someone who can handle the exception, and all information is still there).

其他提示

I like the advice in Joshua Bloch's Effective Java 2nd edition - Throw exceptions appropriate to the abstraction (Item 61).

That is, when faced with a series of exceptions you wish to "percolate" out of your method, consider whether the exceptions should be re-wrapped with something that makes more semantic sense for your method.

Such an approach often has the pleasing side effect of combining several lower-level exceptions into a single higher-level exception.

If you don't know what to do with the exception, you should not catch it. Therefore, your method will now throw an exception, so it should have a throws clause if it is not a runtime exception. There is nothing wrong with them.

Good programming practices tell that you should hide the internal state of your objects from invokers and, at least for me, that also includes Exceptions. You should see what is the meaning of that exception for you and return to the invokers of your class an Exception representing that meaning.

If the framework already offers an exception with that meaning, for example IllegalArgumentException, you should instanciate a new object, give it a string with a good description of what happened and encapsulate the ocurred exception, something along the lines of new IllegalArgumentException("The argument X is invalid because of ...", e); If the framework doesn't has a good descriptive exception for your problem, you should create your own set of exceptions. I normally create a generic exception for that project/package (that will extend Exception or RuntimeException) and derivate exceptions from that. For example, I recently created a generic repository project to be reused across our services and aplication modules to access the database. Since I wanted to abstract invokers from what I was using to access the DB, even from exceptions, I ended up creating some exceptions to encapsulate JPA Hibernate exceptions. I don't have the code here, but it was something similar to:

// implementation package
public abstract class GenericRepository<K, E extends<K>> implements IRepository<K, E>{

    //  constructors

    public final void add(E entity){
        // some code

        try{
            //  code that can throw exceptions
        } catch (EntityExistsException e) {
            //  some code
            throw new EntityAlreadyExistsException(e);
        } catch(RuntimeException e) {
            //  some code
            throw new GenericRepositoryException("An unexpected exception occurred while manipulating the database", e);
        }
    }

    //  some other code

}


// exception package
public final class EntityAlreadyExistsException extends GenericRepositoryException{

    public static final String GENERICMESSAGE = "The entity already exists on the table";

    public EntityAlreadyExistsException(Throwable cause){
        super(GENERICMESSAGE, cause);
    }

    //  other constructors

}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top