-1

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?

davidbak
  • 5,775
  • 3
  • 34
  • 50
  • 1
    [nested wildcards](http://bayou.io/draft/Capturing_Wildcards.html#Nested_Wildcards) – ZhongYu Oct 05 '15 at 22:50
  • @Sotirios - now that I know the [answer](http://stackoverflow.com/a/32959018/7515790) I see it is a duplicate, but I didn't know it then and it isn't an obvious match to this question as it omits anything about nested wildcards, which seems to make it different. – davidbak Oct 06 '15 at 03:09

1 Answers1

3

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;
rgettman
  • 176,041
  • 30
  • 275
  • 357