Busch
Busch

Reputation: 959

How do you throw an instance of an Exception class created through reflection?

I am trying to create a function that throws an exception based on the type that you pass in.

private void myFunc(Class<?> exceptionType) {
   ...do some work...
   throw new exceptionOfTypeExceptionTypePassedIn(newMessage);
}

Can you do this?

Upvotes: 10

Views: 8844

Answers (3)

fafrd
fafrd

Reputation: 1136

Reflection is pretty messy. The accepted answer works, but your code will be harder to follow. You're probably better off refactoring your code to avoid this situation.

Upvotes: -1

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 279930

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.

Upvotes: 11

Software Engineer
Software Engineer

Reputation: 16100

You could use the newInstance method on the Class object.

Upvotes: 1

Related Questions