Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 482
Busch Avatar asked Oct 27 '15 00:10

Busch


2 Answers

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.

like image 61
Sotirios Delimanolis Avatar answered Oct 24 '22 16:10

Sotirios Delimanolis


You could use the newInstance method on the Class object.

like image 34
Software Engineer Avatar answered Oct 24 '22 15:10

Software Engineer