Search code examples
javaenumstype-erasure

What does Java's Enum<?> mean and why isn't it compatible with Enum?


I'm refactoring someone else's code and They use the type Enum<?> in several places. It would be a huge pain to get rid of it, and it seems like it should be compatible with a non-generic Java Enum type declaration since they both having nothing to say about the type parameter to the generic type.

I've created this code snippet to demonstrate the problem that has the compile errors noted in the comments:

enum Shapes {   
  SQUARE,
  CIRCLE 
};

enum Colors {
    RED,
    BLUE,
    GREEN
  };
public void testEnumConversions() throws Exception {
  List<Enum<?>> colors = ImmutableList.<Enum<?>>of(Colors.RED, Colors.GREEN, Shapes.SQUARE);
  List<Enum> colors2 = 
      ImmutableList.<Enum<?>>of(Colors.RED, Colors.GREEN); // incompatible types
  List<Enum> colors3 = 
      (List<Enum>)ImmutableList.<Enum<?>>of(Colors.RED, Colors.GREEN); // inconvertible types
  List<Enum> colors4 = ImmutableList.<Enum>of(Colors.RED, Colors.GREEN, Shapes.SQUARE);
  List<Enum<?>> colors5 = ImmutableList.of(Colors.RED, Colors.GREEN, Shapes.SQUARE);
  List<Enum> colors6 = 
      ImmutableList.of(Colors.RED, Colors.GREEN, Shapes.SQUARE); // incompatible types;

}

Why isn't List<Enum<?>> compatible with List<Enum>? They seem identical to me.


Solution

  • Because everything doesn't say the same as something.

    Same with Comparable. Comparable is Comparable<Object>, so it must be comparable to everything. Comparable<?> says "there is something I can compare it with, but I don't know what.

    Same here: Enum is "Enumeration of everything". Whereas Enum<?> is "Enumeration of something that I do not know".

    This brings us to the difference of List<Enum> to List<Enum<?>>. The first can contain or take enums of arbitrary type. For the latter, all elements must agree.

    I strongly advise against either. Generics are a powerful tool to avoid programming errors. They make your life easier. So understand them, and use them to your advantage. So here, you should be using List<Shapes> and List<Colors>.