I am trying to understand how the @SneakyThrows annotation in Lombok actually works under the hood.
From this SO answer, I can gather it uses the method Lombok.sneakyThrows() under the hood.
The code for Lombok.sneakyThrows() is as follows:
public static RuntimeException sneakyThrow(Throwable t) {
if (t == null) throw new NullPointerException("t");
return Lombok.<RuntimeException>sneakyThrow0(t);
}
@SuppressWarnings("unchecked")
private static <T extends Throwable> T sneakyThrow0(Throwable t) throws T {
throw (T)t;
}
From what I can make out is that all it is doing is casting it to a java.lang.RuntimeException so the compiler does not complain.
But shouldn't that technically give a ClassCastException?
For example:
public static void main(String args[]) {
Throwable i = new InterruptedException();
RuntimeException rr = (RuntimeException) i;
}
The above code results in a ClassCastException.
Then why does the same thing not happen in case of Lombok?
Notice this is not a cast to
RuntimeException, but a cast to a generic parameterT, constrained toThrowable. Because of Type Erasure, this cast cannot be checked. The cast is a completely unchecked cast.The runtime doesn't know what
Tis, except that itextends Throwable. So it can't check whethertactually is aT, and throw an exception if it is not. All it can do is check iftisThrowable, butt's type is alreadyThrowable, so there's no need to do that either.Normally, you would see a warning about this unchecked cast, and that is what
@SuppressWarnings("unchecked")is suppressing.