Java 8 needs a cast while Java 7 didn't - enum.getClass/getDeclaringClass
generics, java, java-8
Solution
Interesting, this is a subtle change in the treatment of raw types.
First, let's clarify your example. The return type of `Object.getClass` is special:
The actual result type is `Class<? extends |X|>` where `|X|` is the erasure of the static type of the expression on which `getClass` is called.
In this case, `X` would be the type parameter `C`, which erases to `Enum`. So `sampleCol.getClass()` returns `Class<? extends Enum>`. `EnumSet.allOf` declares the type parameter `E extends Enum<E>`, and in your case `? extends Enum` is being inferred as its type argument.
The important part is that `Enum` is a raw type. The use of raw types has been seen to erase seemingly unrelated generics, for example on this post: Why won't this generic java code compile? In his answer there, Jon Skeet cites JLS §4.8 ("Raw Types") to cover this unintuitive behavior.
Similar behavior seems to be happening in your example with Java 7: `EnumSet.allOf(sampleCol.getClass())` is allowed to compile with an "unchecked invocation" warning (this gets hidden by the subsequent "unchecked conversion" warning from assigning the resulting raw `EnumSet` to `Set<C>`).
The question becomes: should the occurrence of a raw type in a generic wildcard's bounds allow unchecked conversions? JLS §4.8 makes no mention of this, so it's ambiguous. Possibly it's a bug, but it seems like a reasonable tightening of this behavior. While a standard raw type like `Enum` might itself be expected from legacy APIs, a "half-baked" type like `Class<? extends Enum>` could only occur post-generics and so it doesn't really make sense to let it disrupt generic type checking.
Anyway I'm interested to see if anyone can point to documentation about this change - my search didn't turn anything up.
About your specific code: you should use `getDeclaringClass()` instead. The compiler can't know that calling `getClass` on a `C` will return exactly `Class<C>`; in fact, it won't if used on an enum with a constant-specific class. This is exactly the use case for which `Enum` declares that method.
Problem
I realise Java 8 is still in Beta but this one struck me as odd: ``` public class Fields<C extends Enum<C>> { public Fields(Set<C> columns) { // A sample column used to find the universe of the enum of Columns. C sampleCol = columns.iterator().next(); // Java 8 needs a cast here. Set<C> allColumns = EnumSet.allOf((/*Class<C>)*/ sampleCol.getClass()); // ... there's more to this that I've deleted. } } ``` The error reads: ``` error: incompatible types: inferred type does not conform to equality constraint(s) Set<C> allColumns = EnumSet.allOf(sampleCol.getClass()); inferred: C equality constraints(s): C,CAP#1 where C is a type-variable: C extends Enum<C> declared in class Test.Fields where CAP#1 is a fresh type-variable: CAP#1 extends Enum from capture of ? extends Enum ``` Is this a bug or a new feature of Java 8?