Java 泛型类和泛型方法

Java 泛型类和泛型方法,java,generics,pagination,playframework,Java,Generics,Pagination,Playframework,我正在为我的java项目开发一个分页系统,我想让它对我的各种JPA模型通用 问题是(据我所知),如果我使用泛型,我将不得不以某种方式转换返回的最终值来处理它。我怎样才能避免呢 以下是我到目前为止的代码(绝对不是通用的!) 公共接口分页器{ 公共无效设置限制(整数限制); 公共页面(整型页面); } 公共类PicturesPaginator实现Paginator{ 私有整数限制=10; 私有查询; 私人长数量; 公共PicturesPaginator(字符串查询、对象…参数){ this.quer

我正在为我的java项目开发一个分页系统,我想让它对我的各种JPA模型通用

问题是(据我所知),如果我使用泛型,我将不得不以某种方式转换返回的最终值来处理它。我怎样才能避免呢

以下是我到目前为止的代码(绝对不是通用的!)

公共接口分页器{
公共无效设置限制(整数限制);
公共页面(整型页面);
}
公共类PicturesPaginator实现Paginator{
私有整数限制=10;
私有查询;
私人长数量;
公共PicturesPaginator(字符串查询、对象…参数){
this.query=Picture.find(查询,参数);
this.quantity=Picture.count(查询,参数);
}
@凌驾
公共无效设置限制(整数限制){
这个极限=极限;
}
@凌驾
公共图片页面(整型页面){
如果(第==null页)
page=1;
列表图片=query.fetch(页面,限制);
返回新图片页面(图片、数量、页面、限制);
}
}
公共抽象类页面{
受保护的图片列表;
长期保护量;
受保护的整数页;
保护整数极限;
公开名单(){
返回图片;
}
公共长计数(){
退货数量;
}
公共布尔hasNext(){
退货(第*页限制>数量);
}
公共布尔值hasPrevious(){
返回(第!=1页);
}
公共布尔hasOtherPages(){
return(hasNext()| hasPrevious());
}
公共整数nextPageNumber(){
如果(!hasNext())
返回null;
返回(第+1页);
}
公共整数previousPageNumber(){
如果(!hasPrevious())
返回null;
申报表(第1页);
}
公共整数currentPageNumber(){
返回页面;
}
}
公共类PicturesPage扩展页面{
公共图片页面(列表图片、长数量、整型页面、整型限制){
这个。图片=图片;
这个。数量=数量;
this.page=page;
这个极限=极限;
}
}
我想去掉那些
PicturesPaginator
PicturesPage
并使其通用,但是抽象类页面中的
list()
方法将返回一个通用列表(
list
list
,因为我在这里使用Play)。 我所期望的是这个
list()
方法返回正确的列表,在我的例子中称为
list
。这可能吗

注意:我现在有一个分页模块!框架,我的问题主要是为了进一步了解java:)

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

我希望这个list()方法返回正确的list, 在我的情况下,也就是列表。这可能吗

这不仅仅是可能的,如果你正确使用泛型,你会自动得到它。如果你申报

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

    public List<T> list() {
        return items;
    }
}
公共类页面{
受保护的清单项目;
公开名单(){
退货项目;
}
}
然后像这样使用它:

page = new Page<Picture>();
this.query = Picture.find(query, params);
 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);
 }
page=新页面();

然后
page.list()
实际上将返回一个
list
,因为
T
是一个类型参数,当声明
page
时,它将被一个具体类型所取代。

如果我理解正确,以下内容可能会有所帮助:

使配速通用。转向

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

    public List<Picture> list() {
        return pictures;
    }
公共抽象类页面{
受保护的图片列表;
公开名单(){
返回图片;
}
致:

公共抽象类页面{
受保护的列表元素;
公开名单(){
返回元素;
}
然后将PicturesPage混凝土制成:

public class PicturesPage extends Page<Picture> {
公共类图片页面扩展页面{

我不确定这是否是您需要的,但您可以将Page类转换为:

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;
    }
公共抽象类页面{
受保护的图片列表;
长期保护量;
受保护的整数页;
保护整数极限;
公开名单(){
返回图片;
}
公共长计数(){
退货数量;
}
公共布尔hasNext(){
退货(第*页限制>数量);
}
公共布尔值hasPrevious(){
返回(第!=1页);
}
公共布尔hasOtherPages(){
return(hasNext()| hasPrevious());
}
公共整数nextPageNumber(){
如果(!hasNext())
返回null;
返回(第+1页);
}
公共整数previousPageNumber(){
如果(!hasPrevious())
返回null;
申报表(第1页);
}
公共整数currentPageNumber(){
返回页面;
}

如果我理解正确,您引入泛型的问题如下:

page = new Page<Picture>();
this.query = Picture.find(query, params);
 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);
 }
AFAIK您不能直接调用泛型类型上的静态方法,因此您必须在此处使用反射。在这种情况下,您可能必须将参数类型的类作为参数传递(或从反射数据获取,如果存在),找到要调用的方法并调用它

是这样的:

page = new Page<Picture>();
this.query = Picture.find(query, params);
 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);
 }
您可以查看我的Play--Pagination模块的源代码,以了解我如何处理这类事情

您要做的是使页面也成为通用的,可能是非抽象的:

public class Page<T> {
  public List<T> list() {}
}
公共类页面{
公共列表(){}
}
您可以不使用PicturesPage,只需执行以下操作:

new Page<Picture>()
newpage()
Paginator接口也需要进行泛化:

public interface Paginator {
    public Page<T> page(Integer page);
}
公共接口分页器{
公共页面(整型页面);
}
泛化PicturesPaginator会更加困难,因为您调用Picture类上的方法。Java的泛型实现在运行时擦除类型,因此您必须处理类型标记和反射

public abstract class GenericPaginator<T> {
  public GenericPaginator() {
    Class<T> typeToken = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    // use reflection to invoke the finders methods
  }
}
public class PicturesPaginator extends GenericPaginator<Picture> {}
公共抽象类GenericPaginator{
公共GenericPaginator(){
类别typeToken=(类别)(P