incompatible types and fresh type-variable

Unfortunately, the existing answers don’t explain what’s going on here. First, the solution is to simply specify the type argument to Holder:

Holder<Class<? extends Exception>> exceptionClassHolder;
exceptionClassHolder =
        new Holder<Class<? extends Exception>>(new Exception().getClass());

The reason your version didn’t work is because new Exception().getClass() returns a Class<? extends Exception>, where ? is a wildcard capture (referred to in the compiler error message as CAP#1). Since you use the “diamond operator” with new Holder<>, the compiler infers Class<CAP#1 extends Exception> for T and so Holder<Class<CAP#1 extends Exception>> is the type of the created object.

However, this doesn’t match your declared type of Holder<Class<? extends Exception>>. It uses a nested wildcard, which doesn’t capture: while CAP#1 extends Exception is some specific type extending Exception, the nested ? extends Exception represents literally any type extending Exception.

And while Class<CAP#1 extends Exception> is a subtype of Class<? extends Exception>, Holder<Class<CAP#1 extends Exception>> is not a subtype of Holder<Class<? extends Exception>> because generics aren’t covariant, so the assignment fails.

By manually specifying Class<? extends Exception> for T, you help the compiler avoid this “trap”.

See my similar answers on these posts:

Leave a Comment