如何避免静态通用工厂方法中的“类型不匹配”?

问题描述

| 我不是很笨,无法使用google,或者到目前为止,没有其他人遇到此问题。 我正在尝试编译以下代码
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,在“返回_this; \”行中,出现错误“类型不匹配:无法从MyClass转换为T \” 为什么是这样? T扩展了MyClass,那么问题出在哪里?如果我将行更改为\“ return(T)_this; \”,我只会收到有关未经检查的强制转换的警告,但我不喜欢警告;-)有没有办法实现我想要的内容而不会出现错误或警告?     

解决方法

        假设您有两个实现
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)
会发生什么?这就是为什么您不允许这样做。     ,        那是因为变量
_this
MyClass
类型,而不是type19ѭ类型。即使碰巧包含一个ѭ19实例,编译器也没有办法知道。     ,        我刚刚验证了这可以使编译器感到满意,并且仍然可以按照所需的方式约束类型:
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;
    }
  }
}
编辑: 考虑客户端代码,这实际上只是暴露了该工厂设计中的错误。想象一下:
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!
    ,        \“类型不匹配\” ... ...是由于以下原因:
T
表示of1ѭ的子类。 声明8ѭ返回类型为ѭ19的对象 它返回类型为“ 1”的对象。 就像声明一个返回ѭ28的方法,同时返回it29的方法一样。 解决方案... ...是将return语句更改为
return (T) _this;
(如果要消除警告,请加上
@SuppressWarnings(\"unchecked\")
)。 但是有一个问题... 正如ColinD所指出的:假设您有
class MyClassImpl1 implements MyClass {
}

class MyClassImpl2 implements MyClass {
}
并执行以下操作:
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);