Java 泛型类的方法不适用于传递的参数

标签 java generics

我有一个关于 Java 泛型的“奇怪”问题。

首先我列出我的代码:

服务类

package jse.generics.service;

public interface Service {

}

ServiceProvider.class

package jse.generics.service;

public interface ServiceProvider<T extends Service> {

    public T getService();
}

ServiceProviderRegistry.class

package jse.generics.service;

import java.util.HashMap;
import java.util.Map;

public class ServiceProviderRegistry<T extends Service> {

     private Map<Class<T>, ServiceProvider<T>> map = new HashMap<Class<T>, ServiceProvider<T>>();

     public void register(Class<T> clazz, ServiceProvider<T> provider) {
          map.put(clazz, provider);
     }
}

FooService.class

package jse.generics.service;

public class FooService implements Service {

}

FooServiceProvider.class

package jse.generics.service;

public class FooServiceProvider implements ServiceProvider<FooService> {

     @Override
     public FooService getService() {
          return new FooService();
     }

}

ServiceTest.class

package jse.generics.service;

public class ServiceTest {

     /**
     * @param args
     */
     public static void main(String[] args) {
          ServiceProviderRegistry<? extends Service> registry = new ServiceProviderRegistry<Service>();
          registry.register(FooService.class, new FooServiceProvider());
     }

}

在 ServiceTest 类中,编译器提示 registry.register 方法不适用于传递给它的参数。我真的不知道为什么会这样。所以我期待着你们的帮助来解决这个问题。

最佳答案

在这种情况下,如果 ServiceProviderRegistry 会更好不是参数化类,而是使 register方法(可能还有相应的查找方法)泛型。在您当前的方法中 ServiceProviderRegistry<Service> 只能注册Service.class ,而不是服务的任何子类。

您真正关心的是传递给 register 的类和提供程序相互匹配,这是泛型方法的理想情况。

public class ServiceProviderRegistry {
  private Map<Class<?>, ServiceProvider<?>> registry = new HashMap<>();

  public <T extends Service> void register(Class<T> cls, ServiceProvider<T> provider) {
    registry.put(cls, provider);
  }

  @SuppressWarnings("unchecked")
  public <T extends Service> ServiceProvider<T> lookup(Class<T> cls) {
    return (ServiceProvider<T>)registry.get(cls);
  }
}

您将需要 @SuppressWarnings注释——如果没有一种完全满足编译器的方式,就不可能实现这种模式,编译器只能访问编译时类型。在这种情况下,您知道转换在运行时始终是安全的,因为 register是唯一修改 registry 的东西 map ,所以 @SuppressWarnings是有道理的。 Jon Skeet's answer to this related question总结得很好

Sometimes Java generics just doesn't let you do what you want to, and you need to effectively tell the compiler that what you're doing really will be legal at execution time.

关于Java 泛型类的方法不适用于传递的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16979014/

相关文章:

java - Spring Insight 崩溃并出现 "Imbalanced frame stack"

Java泛型方法参数传递问题

c# - 使用哪个通用集合?

c# - 具有动态端点映射的最小 Api 通用 CRUD

c# - 遍历泛型类的集合属性

java - 是否可以在多核计算机的单核上运行多线程应用程序?

java - jsp从servlet读取文件名不可能吗?

java - 如何在 Gowalla Java (Android) 中获取访问 token

java - 运行问题 "mvn site"

c# - 通用嵌套类型 : cannot convert from X<T> to X<T>