tags:

views:

817

answers:

6

I'm using reflection to add some data to a private variable inside a class from a third-party library. Along the way there are about four different Exceptions that can be thrown; all of them are related to reflection, and all of them are very unlikely to occur. I'm hardcoding the name of the class and variable involved. I'm unlikely to receive any class not found or field not found errors, unless the library gets upgraded some day and has changed significantly.

I'd rather not declare all four of these exceptions for my caller to handle. He's likely to never see them. I'd like to just catch all of these and throw another exception to say "A Java reflection error has occured; it is likely that the library has been upgraded and changed in a way incompatible with this method." Is there a standard Java Exception I can throw that indicates just a general reflection error? Should I define my own? Or would it be best to just declare that this method can throw all of the possible reflection exceptions?

+6  A: 

I usually ask myself these questions:

  • Can whomever calls this method handle these different exception types differently?
  • ...Or would they treat them all the same?
  • Can the caller/user even recover from this error?

If the calling code is likely to treat all four of these exceptions the same (as an unrecoverable error), then it absolutely makes sense to capture each of them and re-throw a more general (single) exception. If you do, make sure you attach the generated exception as an inner exception, just to help any debugging or troubleshooting on the other end.

matt b
+2  A: 

There is some controversy about checked vs unchecked exceptions. Personally I think checked exceptions are the worst idea in Java--but that's just an opinion (however I'm not alone thinking that)

Anyway, I think the important thing would be to change them to either a single unchecked exception. More often than not I use a single one like IllegalStateException or IllegalParameterException--with a clear text description, those two exceptions cover 90% of the crap that can go wrong with a method.

Bill K
A: 

I don't think it makes sense to declare exceptions in this case. So I would catch the exceptions from reflection, maybe log a stack trace, and throw some RuntimeException, which has the advantage that it doesn't need to be declared. You could just use RuntimeException with a suitable message, if you are lazy.

starblue
+1  A: 

First off, don't use reflection unless you really, really have to, because it is evil. Assuming you do have to:

As you are hardcoding all the names, it just leaves Method.invoke, Constructor.newInstance and Field.get/set. I'd suggest just rethrowing the checked exceptions you can deal with wrapped in Error. They shouldn't happen, and if you want to deal with it I suggest doing the check at class intialisation time. InvocationTargetException should, of course, be unwrapped and dealt with in an appropriate manner (throw a wrapped Error for checked exception which the method/constructor did not declare).

Tom Hawtin - tackline
+2  A: 

You can turn all the Exceptions into an AssertionError if you never expect them to occur. InvocationTargetException can be unwrapped if you want to deal with a specific exception. If you want to throw the actual exception thrown by the method rather than InvocationTargetException you can use this trick, but it may be more confusing than useful

} catch (InvocationTargetException e) {
    // Throw any exception in the current thread (even if it is a checked exception)
    Thread.currentThread().stop(e.getCause());
}
Peter Lawrey
why not just throw e.getCause()? Thread.stop() is overkill and deprecated
matt b
Have you tried it? e.getCause() returns a Throwable. How do you throw a Throwable without having to declare it?
Peter Lawrey
+1  A: 

How about having those Exception classes extended from a GeneralException and catch that that GeneralException?

I'll try this right now! :)

Fabio Milheiro
This works perfectly well! Hope this saves someone the trouble you had!
Fabio Milheiro