【发布时间】:2015-01-30 11:30:35
【问题描述】:
我有一个相当复杂的结构,它没有按预期工作。这就是我所做的:
public interface ResultServiceHolder {
<M, ID extends Serializable, BO extends BusinessObject<M, ID>> ResultService<M, ID, BO> getService();
}
public enum ResultTypes implements ResultServiceHolder {
RESULT_TYPE_ONE {
@Override
public ResultOneService getService() { //unchecked conversion?
return serviceInitializer.getResultOneService();
}
},
RESULT_TYPE_TWO {
@Override
public ResultTwoService getService() { //unchecked conversion?
return serviceInitializer.getResultTwoService();
}
},
RESULT_TYPE_THREE {
@Override
public ResultThreeService getService() { //unchecked conversion?
return serviceInitializer.getResultThreeService();
}
};
protected ServiceInitializer serviceInitializer;
protected void setServiceInitializer(ServiceInitializer serviceInitializer) {
this.serviceInitializer = serviceInitializer;
}
@Component
public static class ServiceInitializer {
@Autowired
private ResultOneService resultOneService;
@Autowired
private ResultTwoService resultTwoService;
@Autowired
private ResultThreeService resultThreeService;
@PostConstruct
public void init() {
for(ResultTypes resultType : ResultTypes.values()) {
resultType.setServiceInitializer(this);
}
}
//getters
}
}
目的是基于枚举泛化调用,而只是能够迭代枚举数组。
for(ResultServiceHolder resultServiceHolder : ResultTypes.values()) {
if(resultServiceHolder.equals(post.getPostResultTypeCode())) {
return resultServiceHolder.getService().createResultSearchCriteriaResponse(postId);
}
}
这工作得很好而且花花公子。但是,如果我说
ResultTypes.RESULT_TYPE_ONE.getService().getRepository()
那么它是BaseRepository<Object, Serializable> 而不是BaseRepository<ResultTypeOne, Long>。方法resultTypeHolder.getService()返回ResultService<M, ID, BO>,但最后变成Object和Serializable。
我做错了什么? 如何保留泛型参数类型?
我想补充一点,是的,我确实意识到问题出在未经检查的强制转换的某个地方。但是服务被定义为
public interface ResultTypeOneService
extends ResultService<ResultTypeOne, Long, ResultTypeOneBO> {
}
而且我不知道为什么没有推断出类型。
编辑:从技术上讲,如果我明确推断它们,它就可以工作:
ResultTypes.RESULT_TYPE_ONE.<ResultTypeOne, Long, ResultTypeOneBO>getService().getRepository()
但它应该是自动的,为什么它不能自动工作?我应该为它提供某种包含该类型的对象吗?为什么返回类型还不够呢?
EDIT2:ResultTypeOne 的超类是
@SuppressWarnings("serial")
@EntityListeners(EntityListener.class)
@MappedSuperclass
public abstract class EntityBase implements Serializable {
但它没有映射到边界内的任何地方。
EDIT3:非常感谢@Radiodef!理论上的解决方案最终如下,并且可以正常工作:
public interface ResultServiceHolder<M, ID extends Serializable, BO extends BusinessObject<M, ID>> {
ResultService<M, ID, BO> getService();
}
public abstract class ResultTypes<M, ID extends Serializable, BO extends BusinessObject<M, ID>>
implements ResultServiceHolder<M, ID, BO> {
public static ResultTypes<?, ?, ?>[] values() {
return new ResultTypes<?, ?, ?>[] {RESULT_ONE, RESULT_TWO, RESULT_THREE};
}
public static final ResultTypes<ResultOne, Long, ResultOneBO> RESULT_ONE = new ResultTypes<ResultOne, Long, ResultOneBO>("Result One") {
@Override
public ResultOneService getService() {
return serviceInitializer.resultOneService;
}
};
public static final ResultTypes<ResultTwo, Long, ResultTwoBO> RESULT_TWO = new ResultTypes<ResultTwo, Long, ResultTwoBO>("Result Two") {
@Override
public ResultTwoService getService() {
return serviceInitializer.resultTwoService;
}
};
public static final ResultTypes<ResultThree, Long, ResultThreeBO> RESULT_THREE = new ResultTypes<ResultThree, Long, ResultThreeBO>("Result Three") {
@Override
public ResultThreeService getService() {
return serviceInitializer.resultThreeService;
}
};
protected String name;
protected ServiceInitializer serviceInitializer;
private ResultTypes(String name) {
this.name = name;
}
protected void setServiceInitializer(ServiceInitializer serviceInitializer) {
this.serviceInitializer = serviceInitializer;
}
@Component
static class ServiceInitializer {
@Autowired
private ResultOneService resultOneService;
@Autowired
private ResultTwoService resultTwoService;
@Autowired
private ResultThreeService resultThreeService;
@PostConstruct
public void init() {
for (ResultTypes resultType : ResultTypes.values()) {
resultType.setServiceInitializer(this);
}
}
}
}
我认为由于解决方案变得如此冗长,我将坚持使用enum 方法,并接受这种界限的损失。我不得不添加我自己的values() 实现比我从执行这些界限中获得的损失更多。不过,这是一个有趣的理论练习,再次感谢您的帮助。
【问题讨论】:
-
这不只是一个典型的类型擦除问题吗?
-
@EvanKnowles 可能是这样,但我希望这些类型不会被删除。我的通用
<M, ID, BO> getService()方法出了点问题,无法将ResultTypeOneService解析为<ResultTypeOne, Long, ResultTypeOneBO>。 -
@EvanKnowles 是否可以在调用
getService()中保留类型参数? -
好吧,我迷路了。我不知道如何使这些类型起作用。
-
ResultTypeOne 的超类是什么?
标签: java spring generics enums