简体   繁体   中英

Throwing checked exception in Java

Let's say I am designing an API for storing passwords. According to Effective Java it is a good idea to use throw clauses to show checked exceptions, however by having a throw clause that throws a SQLException, which is a checked exception, then I am revealing the underlying implementation details of my API and thus I will be unable to change the implementation details of my API at a later stage. One of the pros to throwing a checked exception is that the programmer who uses the API should be able to handle the exception in a manner of their choosing. Which of these two methods should I choose to do, add a throw clause which reveals the implementation or hide it or use a different approach?

Your motivation is correct for not "leaking" SQLException to the users of your class.

The fact that you're using SQL could be considered an implementation detail. You may even swap SQL persistence for say, an in-memory one at a later time, and this change shouldn't impact the users of your class.

If you are inclined to use checked exceptions, I would define your own exception type (say, PasswordStoreException -- just an example name). You can use it to wrap the original exception that was thrown, eg:

try {
   // do whatever
} catch (SQLException ex) {
   throw new PasswordStoreException(ex);
}
  1. It is today considered bad design for an API to declare checked exceptions. If you have ever used such an API, you should already know why.
  2. In any case your API should never throw (let alone declare ) exceptions belonging to other APIs. If you do that, you hang a completely unrelated dependency on your client's back. The only "exception" to this rule are JDK's standard exceptions like NPE, ISE and the like.

Catch the SQLException, and wrap it into your own exception:

try {
    // JDBC code
}
catch (SQLException e) {
    throw new MyException("Error persisting the secret", e); // choose a better name, of course
}

Whether this exception should be a checked exception or a runtime exception depends on what the caller can do about it. If it's recoverable (which, I think, is not the case here), it should be a checked exception. If it's not recoverable (the caller can just display an error message), then it should be a runtime exception.

If it's a checked exception, you have no choice; the exception MUST be declared in the throws clause of the method.

Try this..

fillInStackTrace() method is called to re-initialize the stack trace data in the newly created throwable. Will be helpful in masking the info about the exception when tries to access the API.

As is, it is always a good idea to throw your own exception checked/unchecked. But before that, try to fix the underlying exception if possible. I always prefer the below way,

try {
    // JDBC code
}
catch (SQLException e) {
    // try to solve the exception at API level
    bollean solvable = trySolveException(e);
    if (!solvable) {
        // Alert the admin, or log the error statement for further debugging.
        mailClient.sendMailToDBAdmin("Some issue storing password", e); 
        // or
        LOG.severe("some issue in storing password " + e.toString);
        throw MyException("A request/logstatement is logged on your behalf regarding the exception", e);
    }
    LOG.info("The exception is solved");
}
finally {
    // don't forget to free your resources - to avoid garbage and memory leaks, incase you have solved the issue in trySolveException(e).
}

So,

1) You don't expose the SRQException directly, but you throw your own version of the exception.

2) You tried to solve the exception once and if not you alerted somehow - through a mail or a log statement.

3) Finally, you ve released all the resources if you succeed in solving the exception.

The finally clause can be avoided if you use the new Java7's try with resource close option.

For whether to throw checked or unchecked exception, I will give you an example

1) Say an exceptions like NPE - they are programmatic errors and the developer should be more responsible to have not created a NullPointer. You don't expect your code to account for such careless errors and put a try(NPE), catch(NPE). So throw a unchecked exceptions.

2) On the other hand the exceptions like SQL exceptions are at the rare cases, account for some external dependency. So, better throw a user defined checked exceptions. And the user can determine if he can connect to the backup SQL server if any.

3) There are another clause of exceptions, where the program cannot continue furhter. Say a Memory Out of Bounds. They should be thrown as Errors.

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