Solved Need help with Java generics

Discussion in 'Plugin Development' started by Etsijä, May 10, 2014.

Thread Status:
Not open for further replies.
  1. Offline

    Etsijä

    Sorry, this is mostly a Java question but it does relate to a Bukkit plugin I'm writing. I am not at all familiar with Java generics (class templates and stuff), but I need it for my plugin. Here's my class:

    Code:java
    1. public class ListPage {
    2. private List<String> list;
    3. private int page;
    4.  
    5. public ListPage(List<String> list, int page) {
    6. this.list = new ArrayList<String>(list);
    7. this.page = page;
    8. }
    9.  
    10. public void setList(List<String> list) {
    11. this.list = list;
    12. }
    13.  
    14. public void setPage(int page) {
    15. this.page = page;
    16. }
    17.  
    18. public List<String> getList() {
    19. return this.list;
    20. }
    21.  
    22. public int getPage() {
    23. return this.page;
    24. }
    25. }


    The class is very simple and works well for a list of Strings. But how would I generalise it to handle a list of Objects (say, to work with items of my own defined class MyClass)?

    More specifically, in a helper class I have a method paginate(), which handles the pagination of a chat output. I would need to generalise also this method to take a List<MyClass> instead of a List<String>.

    Code:java
    1. public ListPage paginate(List<String> inputList, int page, int itemsPerPage) {
    2. List<String> paginatedList = new ArrayList<String>();
    3. int nItems = inputList.size();
    4. int nPages = nPages(nItems, itemsPerPage);
    5.  
    6. if (page < 1) {
    7. page = 1;
    8. } else if (page > nPages) {
    9. page = nPages;
    10. }
    11.  
    12. int start = (page - 1) * itemsPerPage;
    13. int end = page * itemsPerPage;
    14. if (end > nItems) {
    15. end = nItems;
    16. }
    17.  
    18. paginatedList = inputList.subList(start, end);
    19. ListPage retList = new ListPage(paginatedList, page);
    20. return retList;
    21. }
     
  2. Offline

    oaschi

    Etsijä
    Code:java
    1. public class ListPage<T extends MyClass> {
    2. private List<T> list;
    3. private int page;
    4.  
    5. public ListPage(List<T> list, int page) {
    6. this.list = new ArrayList<T>(list);
    7. this.page = page;
    8. }
    9.  
    10. public void setList(List<T> list) {
    11. this.list = list;
    12. }
    13.  
    14. public void setPage(int page) {
    15. this.page = page;
    16. }
    17.  
    18. public List<T> getList() {
    19. return this.list;
    20. }
    21.  
    22. public int getPage() {
    23. return this.page;
    24. }
    25. }


    That would be your generic ListPage class that only operates with datatypes that are objects of MyClass or objects that extend from MyClass.

    If you want paginate(...) to take only a List of MyClass instead of String then change the datatype from String to MyClass.
     
  3. Offline

    coasterman10

    This would be better asked on StackOverflow or Google, but oaschi has a good example. You can also replace <T extends MyClass> with just <T> to allow any type.
     
  4. Offline

    Etsijä

    Coasterman: thank you, I know the right place for this is SO, but it is soooooo easy to get negative votes there nowadays for asking something "which should be known by studying the issue". Personally I think SO has become way too elitistic to be of any real help to anyone else but professionals.

    Hmm, I'm still not getting the hang of Java generics. I changed the ListPage class into a ListPage <T> class, but now when I'm trying to iterate over the list:
    Code:java
    1. for (String str : pList.getList()) {
    2. sender.sendMessage(ChatColor.DARK_GREEN + str);
    3. }

    I get "Type mismatch: cannot convert from Object to a String".

    If I put in an explicit typecast
    Code:java
    1. for (String str : (List<String>) pList.getList()) {
    2. sender.sendMessage(ChatColor.DARK_GREEN + str);
    3. }
    4.  

    the compiler warns me "Type safety: unchecked cast from List to List<String>". What am I still missing?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 8, 2016
  5. Offline

    Rocoty

    Etsijä Well....did you add the type parameter to the pList variable declaration? Maybe you're going about this the wrong way? Can you be more detailed about what you are trying to achieve, and why you want it?
     
  6. Offline

    Etsijä

    OK, let me explain. I am developing a statistics plugin, which is currently already working pretty well. It uses a SQLite DB in its core, and I have methods to draw out information from that DB as a list of Strings. Each String in that list represents login information on the server. A typical example of data retrieved is this String:

    "2014-05-11 09:34:12 [15:13] Etsija"

    which means: "user Etsija logged into the server at 2014-05-11 09:34:12 and stayed for 15 minutes 13 seconds".

    As I said, the plugin is already working pretty well, but the way I do it is a little cumbersome, as I draw stuff from the database as a String instead of an Object. Therefore, I want to generalise my methods such that they handle a List<MyClass>, rather than List<String>. To achieve this, I have created a new class
    Code:java
    1. public class LoginEntry {
    2. String _playerName;
    3. String _timeLogin;
    4. int _timeOnline;
    5. ...
    6. }
    7.  

    and, I am in the process of changing my methods to handle List<LoginEntry>. But I would like to generalise my methods, since I think all of them are generisable and since I want the methods (if at all possible) to be able to handle a List<String> as well as List<LoginEntry>. This keeps all of my methods working "in the old way" as well as "the new way".
     
  7. Offline

    RawCode

    SupressWarning("RawTypes")

    and you are done with generics in java
     
  8. Offline

    Etsijä

    OK I finally figured it out, and my code is working. Java Generics is quite powerful feature, but you can easily get lost into the template params, whaddayasay:
    Code:java
    1. public <T> ListPage<T> paginate(List<T> inputList, int page, int itemsPerPage)
     
Thread Status:
Not open for further replies.

Share This Page