【发布时间】:2017-11-24 00:05:15
【问题描述】:
我在为特定用例使用泛型实现工厂时遇到问题
我有模型类:
class BaseModel { }
class ModelA extends BaseModel { }
class ModelB extends BaseModel { }
及相应的服务:
class Service<T extends BaseModel> { }
class ServiceA extends Service<ModelA> {}
class ServiceB extends Service<ModelB> {}
我的工厂类,根据它服务的模型创建服务:
class Factory {
private Map<Class<? extends BaseModel>, Class<? extends Service>> registry;
Factory(){
registry = new HashMap<>();
registry.put(ModelA.class, ServiceA.class);
registry.put(ModelB.class, ServiceB.class);
}
Service getService(Class<? extends BaseModel> clazz) throws IllegalAccessException, InstantiationException {
return registry.get(clazz).newInstance();
}
}
还有一个使用工厂的类
class Handler<T extends BaseModel>{
private Service<T> myService;
Handler(Class<T> modelClass) {
Factory fact = new Factory();
try {
myService = fact.getService(modelClass);
} catch (IllegalAccessException | InstantiationException e) {
e.printStackTrace();
}
}
}
我收到一条使用工厂获取服务的线路的警告:
"Unchecked assignment 'Service' to 'Service<T>'"
我明白为什么我会收到消息,因为 getService 方法返回 Service,但我需要 Service<T> 并且对如何更改代码以获取 Service<T> 感到困惑
有什么建议吗?
谢谢!
【问题讨论】:
-
那么方法
getService()有什么返回类型?是Service还是Service<T>? -
您可以使用
<T extends BaseModel> Service getService(Class<T> clazz)并将您的返回值转换为Service<T>。您仍然会在方法本身中收到未经检查的警告,但这是 Java 泛型运行时擦除的弱点之一。 -
有两个问题:第一,没有办法制作一个不同key对应不同泛型类型的Map。根本做不到。其次,没有办法安全地使用反射来创建泛型类型的对象(如
ArrayList<String>或Service<T>)。您最好从服务中消除通用类型。您能否展示一些使用模型子类型的 Service 方法的示例? -
@alfasin 我希望它成为 Service
但我不知道如何实现它。 -
@bcsb1001 如果我需要转换,那么我可以全部使用转换而不是?如果我留下一个警告,那么我可以保留这个实现,你不觉得吗?
标签: java generics design-patterns abstract-factory