Может кто-нибудь объяснить этот код?
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());
}
}
Это может показаться странным, но это не создает исключение приведения и позволяет генерировать проверенное исключение без необходимости объявлять его в подписи или заключать его в непроверенное исключение.
Обратите внимание, что ни sneakyThrow(...)
, ни main не объявляют никаких проверенных исключений, но вывод:
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)
Этот хак используется на Ломбоке с аннотацией @SneakyThrow, которая позволяет генерировать проверенные исключения без их объявления.
Я знаю, что это имеет какое-то отношение к стиранию типа, но я не уверен, что понимаю все части хака.
Редактировать: я знаю, что мы можем вставить Integer
в List<String>
и что различие проверенных и непроверенных исключений является функцией времени компиляции.
При приведении неуниверсального типа, например List
, к универсальному типу, например List<XXX>
, компилятор выдает предупреждение. Но менее распространено прямое приведение к общему типу, например (T) ex
в приведенном выше коде.
Если хотите, часть, которая кажется мне странной, заключается в том, что я понимаю, что внутри JVM List<Dog>
и List<Cat>
выглядят одинаково, но приведенный выше код, похоже, означает, что, наконец, мы также можем присвоить значение типа Cat переменной типа Собака или что-то в этом роде.