Fab Sanchez
Fab Sanchez

Reputation: 58

Java Unchecked Cast Warning: required ArrayList<T>, found ArrayList<Contract>

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

Answers (1)

Lino
Lino

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

Related Questions