Javac issues implementing generics


Attenting Devoxx last week, I had the chance to talk to Joshua Bloch about an compiler issue I had a while ago implementing static factory method pattern from his book. Take this as example:

public class PluginRegistry <T extends Plugin<S>, S> {
  public static <T extends Plugin<S>, S>
    PluginRegistry<T, S> create() {
    return new PluginRegistry();
  }
}

PluginRegistry<Plugin<String>, String> registry =
  PluginRegistry.create();

Don’t try to get the details, there are only three important things:

  1. Two generic parametrizations, where one is a derived one from the other
  2. The static factory method as suggested to ease using this generic class in Josh Blochs “Effective Java 2″ (Item 1)
  3. The last line takes advantage of this method to create an instance of the registry.

The strange thing is, this compiles within Eclipse but does not on plain javac. I mailed Alex Buckley about the issue and after some back and forth he discovered a strange issue with javac.

To let the cat out of the bag: its a bug in javac. Actually according to Maurizio Cimadamore it is a coeffect of some bugs that are actually already marked as fixed (6192945, 6369605, 6193815). I’ll leave out the bloody details, here is, what it boils down to:

Javac somehow only tries to lookup types forward in this case. It infers T == Plugin<String>, but complains that for it Plugin<String> is not a subtype of Plugin<S> (as it has not inferred S yet). Guess what, if you simply switch the generic parameters, it compiles like a charm:

public class PluginRegistry <T extends Plugin<S>, S> {
  public static <S, T extends Plugin<S>>
    PluginRegistry<T, S> create() {
    return new PluginRegistry();
  }
}

PluginRegistry<Plugin<String>, String> registry =
  PluginRegistry.create();

(Note the order of the generic types in the method signature)

Tell me if it’s just me, but now the method signature somehow looks “wrong” to me. As the types are not being derived in the order they are declared at the method. Nevertheless, I at least compiles both on javac and the Eclipse compiler. So keep an eye on stuff like this, if you implement generic types ;). I’ll give you an update if there are further things happen on this.

Information and Links

Join the fray by commenting, tracking what others have to say, or linking to it from your blog.


Other Posts

Write a Comment

Take a moment to comment and tell us what you think. Some basic HTML is allowed for formatting.

Reader Comments

Strangely it doesn’t compile under Mac OSX’s JDK 1.6, even though I tried to switch the generic types on the create method. I’ll get a

incompatible types; no instance(s) of type variable(s) T,S exist so that PluginRegistry conforms to PluginRegistry<Plugin,java.lang.String>.

However, it compiles with Eclipse like a charm.

Damn, seems i forgot the <T, S> stuff at the return type. I’ve fixed it, you should be able to see the expected effect now.

Regards,
Ollie

Ahh now it works, thanks