How to avoid "type mismatch" in a static universal factory method?

Either I'm too stupid to use Google, or no one has yet encountered this problem.

I am trying to compile the following code:

public interface MyClass {
  public class Util {
    private static MyClass _this;
    public static <T extends MyClass> T getInstance(Class<T> clazz) {
      if(_this == null) {
        try {
          _this = clazz.newInstance();
        } catch(Exception e) {
          e.printStackTrace();
        }
      }
      return _this;
    }
  }
}

Howerer, in the line "return _this;" I get the error "Type of mismatch: cannot convert from MyClass to T" Why is this? T extends MyClass, so where is the problem? If I change the line to "return (T) _this;", I just get a warning about an uncontrolled actor, but I don't like the warnings ;-) Is there a way to achieve what I want without an error or warning?

+5
source share
4 answers

, MyClass, Foo Bar. MyClass _this Foo Bar.

, getInstance <T extends MyClass>, :

MyClass myClass = Util.getInstance(MyClass.class);

, , MyClass newInstance().

Foo foo = Util.getInstance(Foo.class);
Bar bar = Util.getInstance(Bar.class);

, , _this Foo Util.getInstance(Bar.class)? .

+6

, _this MyClass, T. , T, .

+4

, , :

public interface MyClass {
  public class Util {
    private static MyClass _this;
      public static MyClass getInstance(Class<? extends MyClass> clazz) {
        if(_this == null) {
          try {
            _this = clazz.newInstance();
          } catch(Exception e) {
            e.printStackTrace();
          }
        }
        return _this;
    }
  }
}

:

, factory. :

MyClass foo = MyClass.getInstance(Foo.class); // sets _this to a Foo and returns it

MyClass bar = MyClass.getInstance(Bar.class); // _this is already set to a Foo and
                                              // we return a Foo when we probably
                                              // are expecting a Bar!
+2

Type Mismatch ...

... due to the following:

  • Tis a subclass MyClass.
  • getInstance declared as a return object of type T
  • Returns an object of type MyClass.

This is like declaring a method to return Double, while it returns some Number.

Decision...

... consists in changing the return statement to

return (T) _this;

(and add @SuppressWarnings("unchecked")if you want to get rid of the warning).

But there's a problem...

As ColinD points out: suppose you have

class MyClassImpl1 implements MyClass {
}

class MyClassImpl2 implements MyClass {
}

and follow these steps:

MyClassImpl1 o1 = MyClass.Util.getInstance(MyClassImpl1.class);
// _this now holds a value of type MyClassImpl1...

// ... which causes this line to throw a ClassCastException.
MyClassImpl2 o2 = MyClass.Util.getInstance(MyClassImpl2.class);
+1
source

All Articles