在我们当前的代码库中,我们有以下数据结构在服务层和前端层之间进行通信:
public class BaseView {
private Integer id;
// Other common attributes and getters/setters;
}
public class BarView extends BaseView {
private String name;
private String Description;
// Other attributes for this object and getters/setters;
}
我们还有一些双扩展类:
public class BazView extends BaseView {
// name, description, other common attributes;
}
public class BazTypeAView extends BazView {
// attributes specific to Type A Baz;
}
public class BazTypeBView extends BazView {
// attributes specific to Type B Baz;
}
在我们的服务层中,我们有实现BaseService的服务方法:BarService
,BazService
,BazTypeAService
,BazTypeBService
以及具有类似命名方案的其他方法所有方法都返回他们负责的类,或者List<class they are responsible for>
。反过来,这些方法中的每一个都从BaseService调用一个带有签名GetObjects(Class Viewtype, Class BeanType, Criteria)
的方法,其中的条件基于传递给特定方法方法的参数。 Bean位于服务层和数据访问层之间,与此无关。
该计划的一个例子:
public interface BaseService {
public BaseView getObject(Class viewType, class beanType, Integer id);
public List<BaseView> getObjects(Class viewType, class beanType, Criteria criteria);
}
public class BaseServiceImpl implements BaseService {
protected BaseView getObject(Class viewType, class beanType, Integer id){
BaseBean bean = (BaseBean) DataService.getobject (beanType, id);
BaseView view = ViewGenerator.createEmptyView(viewType);
copyAttributes(bean, view);
return view;
}
protected List<BaseView> getObject(Class viewType, class beanType, Criteria criteria){
List<BaseBean> bean = (List<BaseBean>) DataService.getobject (beanType, Criteria);
List<BaseView> view = new ArrayList<BaseView>();
copyAttributes(bean, view);
return view;
}
}
public interface BarService extends BaseService {
public BarView getBar(Integer id);
public List<BarView> getBars(BarView barView);
}
public class BarServiceImpl extends BaseServiceImpl implements BarService {
public BarView getBar(Integer id){
BarView bar = getObject(BarView.class, BarBean.class, id);
return bar;
}
public List<BarView> getBars(BarView barView){
Criteria criteria = getCriteriaFromBarView(barView);
List<BarView> bars = getObjects(BarView.class, BarBean.class, criteria);
return bars;
}
}
以上大致是系统的工作原理。创建条形图,获取条形图列表,更新条形图和删除条形图的方法都与上述方法有效。
问题是getObject返回一个原始List,导致很多Eclipse警告和代码难以阅读。我们对这个项目的警告超过2/3是关于原始类型的使用,虽然我们的代码仍然编译并按预期工作,但它有很多消息。
如果我们没有扩展扩展类的第二种View,我们可以只做List<? extends Fooview>
,但这会给扩展BazView的类带来错误。有两种方法可以让泛型类型在这里工作吗?扩展Baseview和? extends X扩展了Baseview?
答案 0 :(得分:2)
除了我猜你的BaseService是一个界面外,我的答案与其他答案没什么不同:
在我们的服务层,我们有服务方法实施一个BaseService
我会定义这样的界面(编辑):
public interface BaseService<T extends FooView>{
T getObject(Class<T> viewType, Class<? extends FooBean> beanType, Integer id);
List<T> getAllObjects(Class<T> viewType, Class<? extends FooBean> beanType);
}
(的 ADDED 强>) 在抽象类中实现该接口要求所有依赖服务也使用泛型:
public abstract class BaseServiceImpl<T extends FooView> implements BaseService<T>{
@Override
public T getObject(Class<T> viewType, Class<? extends FooBean> beanType, Integer id){
FooBean bean = DataService.getObject(beanType, id);
T view = ViewGenerator.createEmptyView(viewType);
copyAttributes(bean, view);
return view;
}
@Override
public List<T> getAllObjects(Class<T> viewType, Class<? extends FooBean> beanType){
List<? extends FooBean> beanList = DataService.getAllObjects(beanType);
return beanList.stream().map(bean -> {
T view = ViewGenerator.createEmptyView(viewType);
copyAttributes(bean, view);
return view;
}).collect(Collectors.toList());
}
private void copyAttributes(FooBean bean, T view){}
}
(修改强>) 所有服务的实施应该是直截了当的:
public class BarServiceImpl extends BaseServiceImpl<BarView> implements BarService{
@Override
public BarView getBar(Integer id){
return getObject(BarView.class, BarBean.class, id);
}
@Override
public List<BarView> getAllBars(){
return getAllObjects(BarView.class, BarBean.class);
}
}
public class BazServiceImpl extends BaseServiceImpl<BazView> implements BazService{
@Override
public BazView getBaz(Integer id){
return getObject(BazView.class, BazBean.class, id);
}
@Override
public List<BazView> getAllBazs(){
return getAllObjects(BazView.class, BazBean.class);
}
}
public class BazTypeAServiceImpl extends BaseServiceImpl<BazTypeAView> implements BazTypeAService{
@Override
public BazTypeAView getBazTypeA(Integer id){
return getObject(BazTypeAView.class, BazTypeABean.class, id);
}
@Override
public List<BazTypeAView> getAllBazTypeAs(){
return getAllObjects(BazTypeAView.class, BazTypeABean.class);
}
}
至少在我的主要方法中没有警告,因为所有内容都是干净的类型:
public class Main{
public static void main(String[] args){
BarService barService = new BarServiceImpl();
BarView barView = barService.getBar(111);
List<BarView> barViewList = barService.getAllBars();
BazService bazService = new BazServiceImpl();
BazView bazView = bazService.getBaz(222);
List<BazView> bazViewList = bazService.getAllBazs();
BazTypeAService bazTypeAService = new BazTypeAServiceImpl();
BazTypeAView bazTypeAView = bazTypeAService.getBazTypeA(333);
List<BazTypeAView> bazTypeAViewList bazTypeAService.getAllBazTypeAs();
}
}
注意:强>
使用抽象类替换接口(如果可能)将再次减少代码,因为两个示例方法都可以在抽象类中实现。主要方法根本不需要改变。
修改强>
您还需要在创建对象的级别使用泛型。否则你需要大量的投射,并且你的列表会收到那些丑陋的警告。我为你更新了样品。
<强> EDIT2 强>
我之前已经提到过 DataService 和 ViewGenerator 也需要使用泛型。这就是我实现方法体的方法:
public class DataService {
public static <T extends FooBean> T getObject(Class<T> beanType, Integer id){return null;}
public static <T extends FooBean> List<T> getAllObjects(Class<T> beanType){return null;}
}
public class ViewGenerator {
public static <T> T createEmptyView(Class<T> viewType){return null;}
}
答案 1 :(得分:0)
如果我理解正确,您需要的是让BaseService
获得将在getObject
方法中使用的通用类型:
BaseService类:
public class <T extends FooView> BaseService<T> {
public T getObject() {
...
}
}
并在具体服务中:
public class BazTypeAService extends BaseService<BazTypeAView> {
...
}
答案 2 :(得分:0)
使用代码样式的快速答案,如果我不理解,我会删除它。
尝试使用这样的通用类型:
public abstract class BarService<T extends FooView>{
List<T> list;
...
public List<T> getList(){ return list;}
}
public class BazService extends BarService<BazView>{
...
}
public class BazTypeBService extends BarService<BazTypeBView>{
...
}
...
在这里,
BazService.getList() will return a List<BazView> instance
BazTypeBService .getList() will return a List<BazTypeBView> instance