【问题标题】:Generics and factory method泛型和工厂方法
【发布时间】:2026-02-16 14:50:02
【问题描述】:

我有两个扩展接口的简单类:

public interface Product 
{

}

public class ProductA implements Product
{

}

public class ProductB implements Product
{

}

我有两个“服务”类:ServiceA 和 ServiceB。每个都与之前定义的产品类之一一起使用。两者都实现了Service接口。

public interface Service<T extends Product>
{
   public void print (T product); 
}

public class ServiceA implements Service<ProductA>
{
  public void print (ProductA product)
  {
      System.out.println("Product A");
  } 
}


public class ServiceB implements Service<ProductB>
{
  public void print (ProductB product)
  {
      System.out.println("Product B");
  }

}

我想开发一个工厂来实例化我的服务:

[在我找到解决方案之前]

public class FactoryService
{
   public static Service<? extends Product> getService (String serviceType)
   {
      Service<? extends Product> s = null;
    
      if ("1".equals(serviceType))              
          s =  new ServiceA();
      else if ("2".equals(serviceType))     
          s = new ServiceB();           
    
      return s;
  }
}

[解决方案]

public static <T> T getService (Type targetType)
{
    T service = null;
    
    if (!targetType.getClass().isInstance(Product.class))
        throw new RuntimeException();
        
    if (ProductA.class.getTypeName().equals(targetType.getTypeName()))
        service = (T) new ServiceA();
    else if (ProductB.class.getTypeName().equals(targetType.getTypeName()))
        service = (T) new ServiceB();
    
    return service;     
}

当我尝试使用我的工厂时,出现编译错误:

[在我找到解决方案之前]

public static void main(String[] args)
{       
    Product pA = new ProductA();
    Product pB = new ProductB();
    Service<? extends Product> service = FactoryService.getService("1");
    service.print(pA);                      
}

[解决方案]

public static void main(String[] args)
{       
    Product pA = new ProductA();
    Product pB = new ProductB();

    Service<Product> service = FactoryService.getService(pA.getClass());
    service.print(pA);
    
    service = FactoryService.getService(pB.getClass());
    service.print(pB);
    
// No compilation errors
    
}

错误提示:

Service 不适用于参数 (Product)。

我该如何解决这个问题?

谢谢

【问题讨论】:

  • 那是因为Service&lt;? extends Product&gt; 不是Service&lt;ProductA&gt;,所以编译器无法检查用ProductA 对象调用它是否正确。请注意,? 并不意味着您可以使用任何 Product 调用它。 ? extends Product 的意思是:“扩展Product 的一些未知类型”。由于确切的类型未知,因此您无法使用它。与您无法在 Java 中向 List&lt;? extends Whatever&gt; 添加任何内容的原因相同。
  • 但是我如何开发一个 FactoryService 类呢?我想获得适当的服务并调用打印方法

标签: java generics factory


【解决方案1】:

当你想使用泛型来声明一个类型时,你不应该像 Jesper 指出的那样使用 &lt;? extends Type&gt;。相反,您应该使用&lt;Type&gt;。在您的情况下,将Service&lt;? extends Product&gt; 替换为Service&lt;Product&gt;
现在你会得到另一个错误:

类型不匹配:无法从 ServiceA 转换为 Service

我建议的解决方案不是定义ServiceAServiceB,而是使用Service#print 方法并检查泛型类型,然后执行必要的操作。在这种情况下不需要FactoryService#getService 方法。

我的解决方案的剧透(先尝试不使用它):

public class Service&lt;T extends Product&gt; {
public void print(T product) {
if (product instanceof ProductA) {
System.out.println("Product A");
} else if (product instanceof ProductB) {
System.out.println("Product B");
}
}
}

【讨论】:

  • 感谢您的帮助。我找到了一个解决方案,虽然我不确定它是否是最好的解决方案。我将用解决方案重新编辑我的问题。
  • 当然!我的解决方案是以防万一您没有找到其他任何东西。干得好!