How do you throw an instance of an Exception class created through reflection?
First, the throw
statement only works with reference expressions of Throwable
or its subtypes. Therefore, the expression you pass to your throw
must have that type. You can achieve this, by providing a bound for the exceptionType
parameter.
private void myFunc(Class<? extends Throwable> exceptionType) {
If you now want to restrict the type of Throwable
subtype, you can do that too.
If it's Exception
, you'll need a throws
declaration
private void myFunc(Class<? extends Exception> exceptionType) throws Exception {
If it's RuntimeException
, it won't
private void myFunc(Class<? extends RuntimeException> exceptionType) {
Depending on what you need, you might actually make the method generic. It would then look like this
private <T extends Throwable> void myFunc(Class<T> exceptionType) throws T {
As for the actual reflection logic, you are making the assumption that the corresponding type has an accessible constructor which accepts a String
argument. If it doesn't, Java will throw all sorts of exceptions of its own. You need to handle these.
A potential solution would look like this (javadoc for Class#getConstructor
, javadoc for Constructor#newInstance
)
private <T extends Throwable> void myFunc(Class<T> exceptionType) throws T {
final String message = "some message";
try {
throw exceptionType.getConstructor(String.class).newInstance(message);
} catch (InstantiationException e) {
e.printStackTrace();
// rethrow
} catch (IllegalAccessException e) {
e.printStackTrace();
// rethrow
} catch (IllegalArgumentException e) {
e.printStackTrace();
// rethrow
} catch (InvocationTargetException e) {
e.printStackTrace();
// rethrow
} catch (NoSuchMethodException e) {
e.printStackTrace();
// rethrow
} catch (SecurityException e) {
e.printStackTrace();
// rethrow
}
}
You can obviously collapse all those exception types into a multi-catch statement.
Note that if the exception type you passed in was one of those mentioned in the existing catch
statements, it will be swallowed, ie. not thrown. You can also add all those in a throws
declaration of its own.
private static <T extends Throwable> void myFunc(Class<T> exceptionType) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, T {
final String message = "some message";
throw exceptionType.getConstructor(String.class).newInstance(message);
}
or rethrow the caught exceptions wrapped in a RuntimeException
.