views:

224

answers:

6

In my project I have a factory method that loads an object that implements an interface. You pass in the class you desire and receive an instantiation of it, like so.

public class Factory {
    public static <E extends SomeInterface> E load( Class<E> clss ) throws Exception {
        return clss.newInstance();
    }
}

You could invoke it like this:

MyObject obj = Factory.load( MyObject.class );

This code works just fine in Eclipse 3.4 with Java 6u13, however today I received a new laptop and installed Eclipse 3.5 and java 6u15 and now I am getting type mismatches everywhere.

MyObject obj = Factory.load( MyObject.class );
               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
               Type mismatch: cannot convert from SomeInterface to MyObject

Putting a cast before Factory on that line makes it go away and all runs well, but it makes the line a bit less clean, and I didn't need it before, so what gives?

A: 

Can't you write

MyObject E = Factory.load( MyObject.class );

drRoflol
THat is exactly the same as my line: `MyObject obj = Factory.load( MyObject.class );` with the variable renamed to E.
banjollity
+1  A: 

Is that all the code required to get this bug? I've seen something very similar in some code I've been looking at today. There was an additional parameter being passed into the equivalent of your Factory method which had a generic type as well. This was missing it's generic definition and I think was to blame for confusing the compiler.

ie, if your factory method looked something like

public class Factory {
    public static <E extends SomeInterface> E load( Class<E> class, Key key ) {
        // return an instance of E
    }
}

Where there is some Key class defined something like this

public class Key<Datatype> {
    ....
}

Giving something like this to invoke the method, note no generics on the declaration of key

Key key = new Key()
MyObject obj = Factory.load( MyObject.class, key );

Hope that helps,

Robin
This is close. I was overlooking a second parameter to my method which was a Collection<Object> (wtf!?). Turns out this was confusing the compiler.
banjollity
A: 

I think this is related to the Java compilance level. By default a project has the default level. Which you set in the Eclipse preferences. In your old installation you will have change it.

+1  A: 

Did you recently add a type parameter to your factory class? There's a pitfall with generic methods on raw types:

  public class FooFactory<UnrelatedArg> {
    public <E> E load(Class<E> c) { ... }
  }

  FooFactory<?> f; f.load(String.class); // returns String
  FooFactory    f; f.load(String.class); // returns Object
ealf
A: 

Post the rest of the code from load.

What class loader are you using in load?