atlantis
atlantis

Reputation: 837

What's the correct method signature for getting the cause of an exception, typecast to the correct type?

I have a method getInstanceOfCause() that accepts an exception class and a Throwable, iterates through the cause of the Throwable and it's causes and returns the instance of the cause that matches the class passed as the first parameter. It looks like this:

public class ExceptionUtil {
    public static <T> T getInstanceOfCause(Class<? extends Throwable> expected, Throwable exc) {
        return (expected.isInstance(exc)) ? (T) exc : getInstanceOfCause(expected, exc.getCause());
    }
}

Let's assume that the expected type is indeed in the "cause-chain" and the call won't cause a NPE. I am able to use it so:

MyException myException = ExceptionUtil.<MyException>getInstanceOfCause(MyException.class, exception);

This is awkward as I have to specify the type twice. Is there any way to rewrite the method signature so that I can use it like below, while still ensuring at compile time that the type is a subclass of Throwable?

MyException myException = ExceptionUtil.getInstanceOfCause(MyException.class, exception);

or

MyException myException = ExceptionUtil.<MyException>getInstanceOfCause(exception);

Upvotes: 1

Views: 31

Answers (1)

Sweeper
Sweeper

Reputation: 271040

Note that T can be inferred from your current method signature. One problem is that you can call it like this:

Foo foo = ExceptionUtil.getInstanceOfCause(MyException.class, exception);

which makes no sense.

I suppose you want to guarantee that the return value type and the type of class for the first parameter are the same?

You can make use of the generic parameter T:

public static <T extends Throwable> T getInstanceOfCause(Class<T> expected, Throwable exc) {
    return (expected.isInstance(exc)) ? (T) exc : getInstanceOfCause(expected, exc.getCause());
}

Note how I constrained T to Throwable, and used it in both Class<T> expected and the return value type. This guarantees that the return value type is the same as the type of the class passed in.

Upvotes: 1

Related Questions