Reputation: 20059
I am trying to create a factory method for a generic Wrapper and I have the problem that I either need to pass in the desired return type (wrapTyped()-method) or I have to explicitly cast an input argument to the desired return type (wrapAuto()-method, 1st use). But I am lazy and don't want to write the extra cast :)
Is there any way to express the declaration of wrapAuto() so that case "wantThis" (at the very bottom) works?
public class GenericFactory {
static class Wrapper<T> {
T wrappdObject;
boolean flag;
String name;
public Wrapper(T wrappedObject, boolean flag, String name) {
this.wrappdObject = wrappedObject;
this.flag = flag;
this.name = name;
}
public T getObject() {
return wrappdObject;
}
// some more irrelevant methods
}
static interface InterfaceType {
}
static class ImplementationA implements InterfaceType {
}
static <U> Wrapper<U> wrapTyped(Class<U> type, U wrappedObject, boolean flag, String name) {
return new Wrapper<U>(wrappedObject, flag, name);
}
static <U> Wrapper<U> wrapAuto(U wrappedObject, boolean flag, String name) {
return new Wrapper<U>(wrappedObject, flag, "NoName");
}
// compiles, but is cumbersome
public Wrapper<InterfaceType> cumbersome = wrapTyped(InterfaceType.class, new ImplementationA(), true, "A");
// compiles, but is also cumbersome
public Wrapper<InterfaceType> alsoUgly = wrapAuto((InterfaceType) new ImplementationA(), true, "B");
// Want this, but "Type mismatch error"
public Wrapper<InterfaceType> wantThis = wrapAuto(new ImplementationA(), false, "C");
}
I stripped it down a little, for simplicity I declared only one set of interface and concrete implementation. I practice the class Wrapper may be used for many completely different, unrelated types.
Upvotes: 0
Views: 770
Reputation: 122429
There is nothing wrong with your method as written. But inference is not perfect. You can always explicitly specify the type arguments:
public Wrapper<InterfaceType> wantThis = GenericFactory.<InterfaceType>wrapAuto(new ImplementationA(), false, "C");
Upvotes: 0
Reputation: 213193
In your method wrapAuto
, add another type parameter, with U
as upper bound, and use it as the formal parameter type:
static <U, T extends U> Wrapper<U> wrapAuto(T wrappedObject, boolean flag, String name) {
return new Wrapper<U>(wrappedObject, flag, "NoName");
}
and then this would work:
Wrapper<InterfaceType> wantThis = wrapAuto(new ImplementationA(), false, "C");
With this invocation, T
is inferred as ImplementationA
, and U
is inferred as InterfaceType
. And the bounds T extends U
perfectly matches these types.
References:
Upvotes: 3