2011-12-12 109 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); 
    ... 
    } 

    ... 
}