title: Using Java Generics with Enums
body: <p><strong>Update:</strong> Thanks for everyone who helped out - the answer to this one lay in what I wasn't noticing in my more complex code and what I didn't know about the Java5 covariant return types. </p>
  
  <p><strong>Original Post:</strong></p>
  
  <p>I've been playing around with something this morning. While I know that I <em>could</em> tackle this whole problem differently, I'm finding myself obsessed with figuring out why it isn't working the way that I was expecting. After spending some time reading around on this, I find I'm no closer to understanding, so I offer it up as a question to see if I'm just being stupid or if there is really something I don't understand going on here.</p>
  
  <p>I have created a custom Event hierarchy like so:</p>
  
  <pre><code>public abstract class AbstractEvent&lt;S, T extends Enum&lt;T&gt;&gt;
  {
      private S src;
      private T id;
  
      public AbstractEvent(S src, T id)
      {
          this.src = src;
          this.id = id;
      }
  
      public S getSource()
      {
          return src;
      }
  
      public T getId()
      {
          return id;
      }
  }
  </code></pre>
  
  <p>With a concrete implementation like so:</p>
  
  <pre><code>public class MyEvent
  extends AbstractEvent&lt;String, MyEvent.Type&gt;
  {
      public enum Type { SELECTED, SELECTION_CLEARED };
  
      public MyEvent(String src, Type t)
      {
          super(src, t);
      }
  }
  </code></pre>
  
  <p>And then I create an event like so:</p>
  
  <pre><code>fireEvent(new MyEvent("MyClass.myMethod", MyEvent.Type.SELECTED));
  </code></pre>
  
  <p>Where my fireEvent is defined as:</p>
  
  <pre><code>protected void fireEvent(MyEvent event)
  {
      for(EventListener l : getListeners())
      {
          switch(event.getId())
          {
              case SELECTED:
                  l.selected(event);
                  break;
              case SELECTION_CLEARED:
                  l.unselect(event);
                  break;
           }
      }
  }
  </code></pre>
  
  <p>So I thought that this would be pretty straightforward but it turns out that the call to event.getId() results in the compiler telling me that I cannot switch on Enums, only convertible int values or enum constants. </p>
  
  <p>It is possible to add the following method to MyEvent:</p>
  
  <pre><code>public Type getId()
  {
      return super.getId();
  }
  </code></pre>
  
  <p>Once I do this, everything works exactly as I expected it to. I'm not just interested in finding a workaround for this (because I obviously have one), I'm interested in any insight people might have as to WHY this doesn't work as I expected it to right off the bat.</p>