2011-12-12 108 views
2

我正在一个分页系统对我的Java项目,我想使它通用对我的各种JPA模型。泛型类和方法

的问题(据我所知)是,如果我使用泛型,我会以某种方式转换返回的最终值进行这项工作。我怎样才能避免这种情况?

这里是我到目前为止的代码(绝对不是一般的!):

public interface Paginator { 
    public void setLimit(Integer limit); 
    public Page page(Integer page); 
} 


public class PicturesPaginator implements Paginator { 
    private Integer limit = 10; 
    private JPAQuery query; 
    private Long quantity; 

    public PicturesPaginator(String query, Object... params) { 
     this.query = Picture.find(query, params); 
     this.quantity = Picture.count(query, params); 
    } 

    @Override 
    public void setLimit(Integer limit) { 
     this.limit = limit; 
    } 

    @Override 
    public PicturesPage page(Integer page) { 
     if (page == null) 
      page = 1; 

     List<Picture> pictures = query.fetch(page, limit); 
     return new PicturesPage(pictures, quantity, page, limit); 
    } 
} 


public abstract class Page { 
    protected List<Picture> pictures; 
    protected Long quantity; 
    protected Integer page; 
    protected Integer limit; 

    public List<Picture> list() { 
     return pictures; 
    } 

    public Long count() { 
     return quantity; 
    } 

    public boolean hasNext() { 
     return (page * limit > quantity); 
    } 

    public boolean hasPrevious() { 
     return (page != 1); 
    } 

    public boolean hasOtherPages() { 
     return (hasNext() || hasPrevious()); 
    } 

    public Integer nextPageNumber() { 
     if (!hasNext()) 
      return null; 

     return (page + 1); 
    } 

    public Integer previousPageNumber() { 
     if (!hasPrevious()) 
      return null; 

     return (page - 1); 
    } 

    public Integer currentPageNumber() { 
     return page; 
    } 
} 


public class PicturesPage extends Page { 
    public PicturesPage(List<Picture> pictures, Long quantity, Integer page, Integer limit) { 
     this.pictures = pictures; 
     this.quantity = quantity; 
     this.page = page; 
     this.limit = limit; 
    } 
} 

我想摆脱那些PicturesPaginatorPicturesPage并使它通用的,但是从抽象类页的list()方法将返回一个通用列表(List<T>List<GenericModel>,因为我在这里使用Play)。 我期望的是这个list()方法返回正确的列表,也就是List<Picture>在我的情况。这可能吗 ?

注:我现在有一个模块分页中播放!框架,我的问题主要是为了解更多关于Java太:)

非常感谢您的帮助,我真的很感激!

回答

3

您可以查看我的P lay - 分页模块的源代码,看看我如何处理这种类型的事情。我把我的source on github

你想要做的是使页面通用性好,而且很可能非抽象:和

public class Page<T> { 
    public List<T> list() {} 
} 

代替PicturesPage你可能只是做:

new Page<Picture>() 

的分页程序界面也将需要被基因化:

public interface Paginator { 
    public Page<T> page(Integer page); 
} 

Generifying PicturesPaginator会更难,因为你调用Picture类中的方法。 Java的泛型实现会在运行时擦除类型,因此您必须处理类型标记和反射。

+0

谢谢你的帮助。我不明白你从Picture类中看到了什么:我只使用来自JPA(find&count)的项目。但最后,我升级我的代码,以允许泛型类使用T扩展GenericModel,我有一个问题:'类 typeToken = ...'抛出此错误:'不能将java.lang.Class转换为java.lang.reflect .ParameterizedType'。我究竟做错了什么? –

+0

Re:图片类,我是指类的方法找到并计算哪个Play!为您提供。 Re:ClassCastException - 我假设你没有像上面描述的那样创建PicturesPaginator,并且扩展了泛型基类的子类,提供了一个参数化类型(“类PicturesPaginator扩展GenericPaginator ”就是一个例子)。另一种方法是将类 typeToken方法参数添加到GenericPaginator的构造函数中。 –

+0

你假设正确! :)我试图将所有内容都移动到一个Class中,将PicturesPaginator的内容移动到Page中。我最终决定将工作直接添加到我的模型中,并使用这些参数调用Page:JPAQuery(find()的结果),Long(count()的结果)。它并不整齐,但至少可以工作。谢谢你的帮助 :) –

1

我期望的是这个list()方法返回正确的List, aka List在我的情况。这可能吗?

这不仅仅是可能的,如果您正确使用泛型,这就是您自动获得的。如果你声明

public class Page<T extends GenericModel>{ 
    protected List<T> items; 

    public List<T> list() { 
     return items; 
    } 
} 

,并使用它像这样:

page = new Page<Picture>(); 

然后page.list()实际上将返回一个List<Picture>,因为T类型参数由一个具体类型更换时Page被宣布。

1

如果我理解正确的话,下面可以帮助:

让佩斯通用。打开

public abstract class Page { 
    protected List<Picture> pictures; 

    public List<Picture> list() { 
     return pictures; 
    } 

到:

public abstract class Page<Element> { 
    protected List<Element> elements; 

    public List<Element> list() { 
     return elements; 
    } 

不是让PicturesPage形而下:

public class PicturesPage extends Page<Picture> { 
1

我不知道这是否是您所需要的,但你可以在页面类转换到本:

public abstract class Page<T> { 
    protected List<T> pictures; 
    protected Long quantity; 
    protected Integer page; 
    protected Integer limit; 

    public List<T> list() { 
     return pictures; 
    } 

    public Long count() { 
     return quantity; 
    } 

    public boolean hasNext() { 
     return (page * limit > quantity); 
    } 

    public boolean hasPrevious() { 
     return (page != 1); 
    } 

    public boolean hasOtherPages() { 
     return (hasNext() || hasPrevious()); 
    } 

    public Integer nextPageNumber() { 
     if (!hasNext()) 
      return null; 

     return (page + 1); 
    } 

    public Integer previousPageNumber() { 
     if (!hasPrevious()) 
      return null; 

     return (page - 1); 
    } 

    public Integer currentPageNumber() { 
     return page; 
    } 
1

如果我理解正确,你的概率LEM与引入泛型这里有线路是这样的:

this.query = Picture.find(query, params); 

AFAIK你不能在泛型类型调用静态方法直接,所以你要在这里使用反射。在这种情况下,您可能必须将参数类型的类作为参数传递(或者如果它存在,则从反射数据中获取它),找到要调用并调用的方法。

这件事情是这样的:

Class<T> clazz; 

public Paginator (Class<T> clazz) { 
    this.clazz = clazz; 

    //note that you need to handle exceptions, I'll leave them out for brevity 
    Method findMethod = clazz.getMethod("find", String.class, Array.class); 
    this.query = findMethod.invoke(null, query, params); 
} 

编辑

作为替代方案,通过一个“取景器”对象到通用Paginator,并使其实现,提供了find(...)count(...)方法的接口:

interface Finder<T> { 
    JPAQuery find(String query, Object... params); 
    Long count(String query, Object... params); 
} 

class Paginator<T, F extends Finder<T>> { 
    public Paginator(F finder, String query, Object... params) { 
    this.query = finder.find(query, params); 
    ... 
    } 

    ... 
}