First, I should say that I am able to get the generic type of instances or anonymous inner classes.
Here is the code example, look for the catch block:
public static interface MyInterface<E extends Throwable>{
void call() throws E;
}
public static <E extends Throwable> void method(MyInterface<E> lambda) throws E {
try {
lambda.call();
} catch(Throwable ex) {
// Pseudo code
Class<?> T = ((ParameterizedType)ex.getClass().getGenericInterfaces()[0]).getActualTypeArguments()[0];
if ( T.isInstance(ex) ) {
throw ex;
} else {
...
}
}
}
public static void throwsException() throws Exception {
throw new Exception();
}
This doesn't work:
method(() -> {
throwsException();
});
But this does:
method(new MyInterface<Exception>() {
@Override
public void call() throws Exception {
throwsException();
}
});
But with the introduction of Lambdas, i can no longer enforce this!
It should also be noted that this now potentially breaks backwards compatibility with Libraries older than < 8, and that reflected out this information.
I have researched this topic, and there only seems to be possible workarounds for getting the method parameters, but this is regarding the throws part so that won't work.
Note: I have seen this thread already: Reflection type inference on Java 8 Lambdas
getGenericInterfacesworks by returning what appears in the source code. With lambdas, you don't have an actual type argument.getGenericInterfacesis what appears in the source code (ie. compile time), not the type that was potentially inferred at some method invocation (they they could sometimes be the same).getGenericInterfacesonly works with direct implementations. Your solution will fail if you add a level of indirection, ie. an extra interface or subtype in between the instance type and theMyInterfaceinterface. It will also fail if you provide aProxyinstance that implementsMyInterface. Your parameter typeMyInterface<E>can only restrict the type of the expression. It cannot restrict how that type was generated, whether compile time or runtime.interface Some extends MyInterface<Exception>andclass SomeImpl implements Some. You can usemethod(new SomeImpl());, but thegetGenericSuperclass"hack" will not work.getGenericInterfacesrather thangetGenericSuperclassfor this case. You might want to look into type tokens and why/how they work too.