views:

319

answers:

2

Hello, everyone!

I thought, I would understand Java generics by now. But now I'm helpless again.

I have a generic class where a c-tor constructs correctly-typed instance, while a static factory method produces a type mismatch.

Please look at the following code:

public class _GenericFactoryMethods {

  public final static class DemoClass<T1, T2> {
    private final T1 _1;
    private final T2 _2;

    // static factory method
    public static <T1, T2> DemoClass<T1, T2> create(T1 _1, T2 _2) {
      return new DemoClass<T1, T2>(_1, _2);
    }

    // usual c-tor
    public DemoClass(T1 _1, T2 _2) {
      this._1 = _1;
      this._2 = _2;
    }

    public T1 get1() { return _1; }

    public T2 get2() { return _2; }
  }

  public void doSomething() {
    String str = "test";

    Class<? extends CharSequence> _1 = str.getClass();
    CharSequence _2 = str;

    // works
    DemoClass<Class<? extends CharSequence>, CharSequence> dc1 =
        new DemoClass<Class<? extends CharSequence>, CharSequence>(_1, _2);

    // compile error
    DemoClass<Class<? extends CharSequence>, CharSequence> dc2 =
        DemoClass.create(_1, _2);
  }

}

The error is:

Uncompilable source code - incompatible types
required: _GenericFactoryMethods.DemoClass<java.lang.Class<? extends java.lang.CharSequence>,java.lang.CharSequence>
found:    _GenericFactoryMethods.DemoClass<java.lang.Class<capture#794 of ? extends java.lang.CharSequence>,java.lang.CharSequence>

Please help to understand and to solve this.
(I really need static factory methods for some of such classes).

EDIT
Can someone also explain why explicit type parameters must be used?

+1  A: 

In this case, you have to explicitly set the generic type:

dc2 = DemoClass.<Class<? extends CharSequence>, CharSequence>create(_1, _2);
sfussenegger
+4  A: 

Try

DemoClass.<Type1, Type2>create(_1, _2);

As I remember from Josh Bloch's presentation of his Effective Java 2nd Edition: "God kills a kitten every time you specify an explicit type parameter". Try to avoid constructions like this.

Roman
Thank you. Well, to write the usual constructor is even longer ;) And for my special case (**not** the example) I really need static factory methods.
java.is.for.desktop
Sigh, there's no chance to beat answers mentioning kittens. Chapeau! ;)
sfussenegger
@sfussenegger: yeah, it's kinda cheating, everyone loves kittens )))
Roman