Reputation: 12655
I have a generic function which does something and, in case of failure, it should throw a specific exception.
To simplify you can imagine it as such:
public static <E extends Exception> void doSomething(Class<E> exceptionClass) throws E {
try {
//Do stuff
} catch (Exception e) {
String message = "...";
//-> here I want to throw a new exception of type E with the message I built above and the caught exception as cause
}
}
In order to do that, what I can think about is to build a new E by reflection and throw an unchecked exception if any of the exceptions that can be thrown during reflection is actually thrown:
public static <E extends Exception> buildException(Class<E> exceptionClass, String msg, Throwable cause) {
try {
return exceptionClass.getDeclaredConstructor(String.class, Throwable.class).newInstance(msg, cause);
} catch (NoSuchMethodException ... e) {
//Catch everything that can be thrown
throw new RuntimeException(e);
}
}
... and then call it simply throw buildException(exceptionClass, message, e)
inside the main function.
However I don't like too much this solution because I need to get the class in parameter from the caller (while they are already inferring me the type via E) and I may as well have to throw a Runtime exception if my reflection operation fails (all E extends Exception so the constructor I look for should always be there, but we never know if the caller doesn't customize the exception too much...)
Although the drawbacks, I can't get anything better into my mind.
Does anyone have some better design ideas for this?
Note: about the need. I have several classes which perform the same operation (the "do stuff") but that need to throw a specific exception (class 1 throws exception 1, class 2 throws exception 2 etc.) which wraps any possible exception thrown while performing the "do stuff" operation. Of course I may move the catch on caller side but that would make a lot of code duplication for the exact same operation.
Upvotes: 2
Views: 66
Reputation: 17567
Instead of passing the class and let the called method handle the exception creation you could let the calling method handle it instead. This is possible by accepting a function:
public static <E extends Exception> void doSomething(Function<String, E> exceptionFunction) throws E {
try {
//Do stuff
} catch (Exception e) {
String message = "...";
throw exceptionFunction.apply(message);
}
}
This function would expect a String, your message, and will then return an instance of the exception to be thrown. As you can see, you can trigger the function by using exceptionFunction.apply(message)
.
You can also use e
to add the "cause" stacktrace:
public static <E extends Exception> void doSomething(Function<String, E> exceptionFunction) throws E {
try {
//Do stuff
} catch (Exception e) {
String message = "...";
var exception = exceptionFunction.apply(message);
exception.initCause(e);
throw exception;
}
}
The call of the doSomething
method would then look like this:
doSomething((s) -> new MyException());
or if you prefer method references, like this:
doSomething(MyException::new);
(mind that MyException would need a constructor with a String parameter)
Upvotes: 1