Ответ 1
К сожалению, существующие ответы не объясняют, что происходит здесь. Во-первых, решение состоит в том, чтобы просто указать аргумент типа Holder
:
Holder<Class<? extends Exception>> exceptionClassHolder;
exceptionClassHolder =
new Holder<Class<? extends Exception>>(new Exception().getClass());
Причина, по которой ваша версия не работает, состоит в том, что new Exception().getClass()
возвращает Class<? extends Exception>
, где ?
является подстановочный знак (упоминается в сообщении об ошибке компилятора как CAP#1
). Поскольку вы используете "алмазный оператор" с new Holder<>
, компилятор выводит Class<CAP#1 extends Exception>
для T
и поэтому Holder<Class<CAP#1 extends Exception>>
- это тип созданного объекта.
Однако это не соответствует объявленному типу Holder<Class<? extends Exception>>
. Он использует вложенный подстановочный знак, который не захватывает: while CAP#1 extends Exception
- это определенный тип расширения Exception
, вложенный ? extends Exception
представляет буквально любой тип, расширяющий Exception
.
И хотя Class<CAP#1 extends Exception>
является подтипом Class<? extends Exception>
, Holder<Class<CAP#1 extends Exception>>
не является подтипом Holder<Class<? extends Exception>>
, потому что generics не являются ковариантными, поэтому присваивание не выполняется.
Ручным указанием Class<? extends Exception>
для T
, вы поможете компилятору избежать этой "ловушки".
См. мои похожие ответы на эти сообщения: