Search code examples
javagenericsbounded-wildcardsubtypingunbounded-wildcard

Casting bounded wildcard to unbounded wildcard within a generic type is an error (X<Y<? extends T>> to X<Y<?>>


Consider this sample:

private <T> void m(Class<? extends T> k, Set<Class<? extends T>> sk) {
    Class<?> ku = k;
    Set<Class<?>> sku = sk; // <-- Type mismatch: cannot convert from
                            //     Set<Class<? extends T>> to Set<Class<?>>
}

In other words, I can assign a Class<? extends T> to a Class<?> for some arbitrary T but not a Set<Class<? extends T>> to a Set<Class<?>>.

It probably has something to do with some limitation on covariance/contravariance, but what?

I could introduce a cast: Class.class::cast would do it. But is there a way to bend the compiler to my will with subtle type-fu rather than bashing it in the head with a cast?


Solution

  • Even though a Class<? extends T> is a Class<?>, a Set<Class<? extends T>> is not a Set<Class<?>>, for the same reason that even though a Dog is an Animal, a List<Dog> is not a List<Animal>. Here, ? extends T has the same role as Dog, and ? has the same role as Animal.

    You'll need a ? extends in front of Class to get this to compile correctly.

    Set<? extends Class<?>> sku = sk;