Java 泛型通配符为“和”;扩展;及;超级";

Java 泛型通配符为“和”;扩展;及;超级";,java,generics,wildcard,Java,Generics,Wildcard,我正在从事一个需要将服务添加到组件的项目。服务类是一个没有任何方法的接口。以下是我的服务如何工作的示例: public interface Service { } public interface CarWash extends Service { void washCar(Car car); } public interface CarRepair extends Service { void repairCar(Car car); } 现在有许多这些服务的实现。一个类可以实现多

我正在从事一个需要将服务添加到组件的项目。
服务
类是一个没有任何方法的接口。以下是我的服务如何工作的示例:

public interface Service { }

public interface CarWash extends Service {
  void washCar(Car car);
}

public interface CarRepair extends Service {
  void repairCar(Car car);
}
现在有许多这些服务的实现。一个类可以实现多个服务,如车库类:

public class Garage implements CarWash, CarRepair {
  @Override
  public void washCar(Car car) { /* .. */ }
  @Override
  public void repairCar(Car car) { /* .. */ }
}
向组件添加服务时,我不想在所有任务中都使用该服务,但例如,仅将
车库
用于洗车(
CarWash
),而不用于修理汽车(
CarRepair
)。因此,我将任务指定为类,如下所示:

void addService(Service service, Class<? extends Service> task);
我正在寻找一种方法来指定
服务
需要实现(扩展)
任务
,而
任务
正在扩展
服务
接口,
如下(不编译):

addService(T service,Class我认为
void addService(S service,Class clazz)
听起来符合您的标准:

public static class Foo {                                                                                   
  public interface Service { }                                                                          

  public interface CarWash extends Service {                                                            
    void washCar();                                                                                     
  }                                                                                                     

  public interface CarRepair extends Service {                                                          
    void repairCar();                                                                                   
  }                                                                                                     

  static <T extends Service, S extends T> void addService(S service, Class<T> clazz) {}                 

  public static void main(String[] args) {                                                              
    addService(null, CarWash.class);  // Fine.                                                                  
    addService(null, Object.class);   // Compilation error.                                                          
  }
}
公共静态类Foo{
公共接口服务{}
公共接口洗车扩展服务{
使洗车无效();
}                                                                                                     
公共接口CarRepair扩展服务{
无效维修车();
}                                                                                                     
静态void addService(S服务,类clazz){}
公共静态void main(字符串[]args){
addService(null,CarWash.class);//很好。
addService(null,Object.class);//编译错误。
}
}

(我添加了一些static,并从方法签名中删除了
Car
,因为我没有要编译的定义)

这也可以,具体取决于您如何使用
服务的类型:

<T extends Service> void addService(T service, Class<T> task)

我唯一的问题是varargs强制所有数组元素都属于同一类型,因此我无法编写
addService(null,CarWash.class,CarRepair.class);

对于Java泛型来说,这实际上是一个困难的问题。(C++可以用它来实现,这是Java不太可能获得的特性。)

因此,用Java解决这个问题的一种方法是运行时验证,例如:

<T extends Service> void addService(
        T service, Class<? super T> tasks...) {
    for(Class<? super T> task : tasks)
        if(!Service.class.isAssignableFrom(tasks))
            throw new IllegalArgumentException();
}
void addService(

T service,Class关于:
void addService(S service,Class clazz);
?有效,非常感谢!我唯一的问题是varargs强制所有数组元素为相同类型,因此我无法编写
addService(null,CarWash.Class,CarRepair.Class)
。现在您没有询问varargs…这听起来像是一种情况,您无论如何都不想使用数组,应该更喜欢使用Iterable,例如
静态void addService(S service,IterableI同意。我认为可以将其作为一个参数,并多次调用该方法来为多个任务添加服务,就像您在回答中所做的那样。
public static class Foo {                                                                                   
  public interface Service { }                                                                          

  public interface CarWash extends Service {                                                            
    void washCar();                                                                                     
  }                                                                                                     

  public interface CarRepair extends Service {                                                          
    void repairCar();                                                                                   
  }                                                                                                     

  static <T extends Service, S extends T> void addService(S service, Class<T> clazz) {}                 

  public static void main(String[] args) {                                                              
    addService(null, CarWash.class);  // Fine.                                                                  
    addService(null, Object.class);   // Compilation error.                                                          
  }
}
<T extends Service> void addService(T service, Class<T> task)
addService(new Garage(), CarWash.class); // OK, Garage is a CarWash
<T extends Service> void addService(
        T service, Class<? super T> tasks...) {
    for(Class<? super T> task : tasks)
        if(!Service.class.isAssignableFrom(tasks))
            throw new IllegalArgumentException();
}