实例化通用类中使用的对象实例的工厂方法

时间:2018-09-15 08:17:24

标签: java generics factory generic-programming

我有以下课程。

public abstract class AbstractClass {

      protected String value1;

      public void setValue1(String value1) {
           this.value1 = value1;
      }

}

public abstract class ConcreteClass1 extends AbstractClass{

}

public abstract class ConcreteClass2 extends AbstractClass {

}

public class FactoryOfAbstractClass {

   public AbstractClass newInstance(Class responseType) {
      if (responseType == ConcreteClass1.class) {
         return new ConcreteClass1();
      } else if (responseType == ConcreteClass2.class) {
         return new ConcreteClass2();
      }
      return null;

}

public abstract class ServiceClass<T extends AbstractClass> {

   public T method1 (String arg1, String arg2, Class responseType) {

      //Some operations resulting in a variable called value1
      String value1= someOp();
      T result = FactoryOfAbstractClass.newInstance(responseType);
      result.setValue1(value1);
      return result;

   }

}

T result = FactoryOfAbstractClass.newInstance(responseType);行中,我收到一个编译错误,指出我需要对要到达T的对象进行类型转换。由于我的工厂方法正在返回,因此我不理解编译错误。抽象类的实例和服务类的通用T extends AbstractClass

一旦我将其转换为T,编译问题就消失了。但是我不明白为什么我们首先需要进行类型转换。为什么需要类型转换?

另一种选择是不使用工厂,而使用responseType.newInstance()。但这在内部使用反射,我想避免它们。 我可以采取其他方法吗?

1 个答案:

答案 0 :(得分:3)

  

我不理解编译错误,因为我的工厂方法正在返回Abstract类的实例,而服务类的通用T扩展了AbstractClass

让我们将AbstractClass替换为Car,以获得更容易理解的解释。假设程序员创建了ServiceClass<Mercedes>(Mercedes是Car的类型,对吗?)。 FactoryOfAbstractClass.newInstance()的返回类型为Car。因此,编译器不知道此方法返回的Car的具体类型。它可以是梅赛德斯,但也可以是福特,标致或大众。但是,您将结果分配给T(在本例中为Mercedes)。因此,如果没有强制转换,就无法编译。

坦率地说,这个工厂是完全没有必要的。由于调用者应该传递该类以使用,因此您可以仅使用该类的实例而不是工厂,从而让调用者创建该实例。或者,您可以将Supplier<AbstractClass>作为参数,而调用方只需传递ConcreteClass1::new。这将使代码更简单,更安全和更可扩展(因为您将不仅限于两个已知的子类)。