Reputation: 58
I'm adding Generics to my pagination class in Java. I am having trouble fixing the code to avoid these 'unchecked cast' warnings on method public ArrayList<T> getNextPage()
Warning: java: unchecked cast
required: java.util.ArrayList<T>
found: java.util.ArrayList<Contract>
On:
return (ArrayList<T>) getPaginatedContracts(startRow, pageSize);
Warning: java: unchecked cast
required: java.util.ArrayList<T>
found: java.util.ArrayList<Job>
On:
return (ArrayList<T>) getPaginatedJobs(startRow, pageSize);
At the moment T
can either be a Contract
or a Job
.
Is there another way to return ArrayList<T>
which correctly uses Generics without any warnings?
Or since my Constructor takes a Class<T>
and does some type checking: E.g. if (clazz.isAssignableFrom(Contract.class)) {...}
is it acceptable for me to use @SuppressWarnings("unchecked")
on getNextPage()
?
public class PaginationWrapper<T> {
private Class<T> clazz;
private int currentPage;
private int pageSize;
public PaginationWrapper(Class<T> clazz) {
this.clazz = clazz;
this.currentPage = -1;
this.pageSize = 100;
}
private static ArrayList<Contract> getPaginatedContracts(int startRow, int pageSize) {
ArrayList<Contract> list = new ArrayList<>(pageSize);
// Get info from database
return list;
}
private static ArrayList<Job> getPaginatedJobs(int startRow, int pageSize) {
ArrayList<Job> list = new ArrayList<>(pageSize);
// Get info from database
return list;
}
public ArrayList<T> getNextPage() {
currentPage++;
int startRow = currentPage * pageSize;
if (clazz.isAssignableFrom(Contract.class)) {
// Warning: java: unchecked cast
// required: java.util.ArrayList<T>
// found: java.util.ArrayList<Contract>
return (ArrayList<T>) getPaginatedContracts(startRow, pageSize);
} else if (clazz.isAssignableFrom(Job.class)) {
// Warning: java: unchecked cast
// required: java.util.ArrayList<T>
// found: java.util.ArrayList<Job>
return (ArrayList<T>) getPaginatedJobs(startRow, pageSize);
}
return null;
}
static class Contract {
}
static class Job {
}
public static void main(String[] args) {
PaginationWrapper<Contract> contractWrapper = new PaginationWrapper<>(Contract.class);
ArrayList<Contract> paginatedList = contractWrapper.getNextPage();
}
}
Upvotes: 1
Views: 374
Reputation: 19926
You could make that class abstract and then the subclass has to implement the actual database call:
public abstract class PaginationWrapper<T> {
private int currentPage = 1;
private int pageSize = 100;
public ArrayList<T> getNextPage() {
currentPage++;
int startRow = currentPage * pageSize;
// here we delegate to the implementation
return getNextPage(startRow, pageSize);
}
protected abstract ArrayList<T> getNextPage(int startRow, int pageSize);
}
And then create 2 subclasses
public class JobPagination extends PaginationWrapper<Job> {
protected ArrayList<Job> getNextPage(int startRow, int pageSize) {
return /* list from database */
}
}
public class ContractPagination extends PaginationWrapper<Contract> {
protected ArrayList<Contract> getNextPage(int startRow, int pageSize) {
return /* list from database */
}
}
Now the general logic is packed into the PaginationWrapper
but the actual database logic resides now in the specific subclass.
Upvotes: 1