关于
Java泛型,我有一个“奇怪”的问题.
@H_404_2@首先我列出我的代码:
@H_404_2@Service.class
package jse.generics.service; public interface Service { }@H_404_2@ServiceProvider.class
package jse.generics.service; public interface ServiceProvider<T extends Service> { public T getService(); }@H_404_2@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); } }@H_404_2@FooService.class
package jse.generics.service; public class FooService implements Service { }@H_404_2@FooServiceProvider.class
package jse.generics.service; public class FooServiceProvider implements ServiceProvider<FooService> { @Override public FooService getService() { return new FooService(); } }@H_404_2@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()); } }@H_404_2@在ServiceTest类中,编译器抱怨registry.register方法不适用于传递给它的参数.我真的不知道为什么会发生这种情况.所以我很期待你的帮助来解决这个问题.
解决方法
在这种情况下,如果ServiceProviderRegistry不是参数化类,而是使寄存器方法(可能是相应的查找方法)通用,那么你会更好.在您当前的方法中,ServiceProviderRegistry< Service>只能注册Service.class,而不能注册Service的任何子类.
@H_404_2@你真正关心的是传递给寄存器的类和提供者相互匹配,这是泛型方法的理想情况.
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); } }@H_404_2@您将需要@SuppressWarnings注释 – 如果没有完全满足编译器的方式,则无法实现此模式,编译器只能访问编译时类型.在这种情况下,您知道强制转换在运行时始终是安全的,因为寄存器是唯一修改注册表映射的东西,因此@SuppressWarnings是合理的. Jon Skeet’s answer to this related question非常好地总结了它
@H_404_2@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.