Java SneakyThrow de exceções, digite eliminação
Alguém pode explicar esse código?
public class SneakyThrow {
public static void sneakyThrow(Throwable ex) {
SneakyThrow.<RuntimeException>sneakyThrowInner(ex);
}
private static <T extends Throwable> T sneakyThrowInner(Throwable ex) throws T {
throw (T) ex;
}
public static void main(String[] args) {
SneakyThrow.sneakyThrow(new Exception());
}
}
Pode parecer estranho, mas isso não produz uma exceção de conversão e permite lançar uma exceção verificada sem precisar declará-la na assinatura ou envolvê-la em uma exceção não verificada.
Observe que nemsneakyThrow(...)
ou os principais estão declarando qualquer exceção verificada, mas a saída é:
Exception in thread "main" java.lang.Exception
at com.xxx.SneakyThrow.main(SneakyThrow.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Este hack é usado no Lombok, com a anotação @SneakyThrow, que permite lançar exceções verificadas sem declará-las.
Eu sei que tem algo a ver com o apagamento de tipos, mas não tenho certeza de entender todas as partes do hack.
Editar: Eu sei que podemos inserir umInteger
em umList<String>
e essa distinção de exceções marcadas / não verificadas é um recurso de tempo de compilação.
Ao transmitir de um tipo não genérico comoList
para um tipo genérico comoList<XXX>
o compilador produz um aviso. Mas é menos comum lançar um tipo genérico diretamente como(T) ex
no código acima.
Se você quiser, a parte que parece estranha para mim é que eu entendo que dentro da JVM umList<Dog>
eList<Cat>
parece o mesmo, mas o código acima parece significar que finalmente podemos também atribuir um valor do tipo Cat a uma variável do tipo Dog ou algo parecido.