Предупреждение Java Unchecked Cast: требуется ArrayList<T>, найден ArrayList<Contract>

Я добавляю Generics в свой класс разбивки на страницы в Java. У меня возникли проблемы с исправлением кода, чтобы избежать этих предупреждений о «непроверенном приведении» в методе public ArrayList<T> getNextPage()

Предупреждение: java: непроверенное приведение
требуется: java.util.ArrayList<T>
Найдено: java.util.ArrayList<Контракт>

Далее:
return (ArrayList<T>) getPaginatedContracts(startRow, pageSize);

Предупреждение: java: непроверенное приведение
требуется: java.util.ArrayList<T>
Найдено: java.util.ArrayList<Job>

Далее:
return (ArrayList<T>) getPaginatedJobs(startRow, pageSize);

На данный момент T может быть либо Contract, либо Job.

Есть ли другой способ вернуть ArrayList<T>, который правильно использует дженерики без каких-либо предупреждений?

Или, поскольку мой конструктор принимает Class<T> и выполняет некоторую проверку типов: например.
if (clazz.isAssignableFrom(Contract.class)) {...}
Можно ли использовать @SuppressWarnings("unchecked") на 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();
    }
}

Если вы выполняете нетривиальное приведение, то следует отметить идущий. Такие гипсы по своей сути небезопасны.

John Bollinger 18.02.2019 16:32

Зачем вообще использовать дженерики? На мой взгляд, не имеет особого смысла. Поскольку вы могли бы просто вызвать конкретный метод напрямую

Lino 18.02.2019 16:33
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
93
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете сделать этот класс абстрактным, а затем подкласс должен реализовать фактический вызов базы данных:

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);
}

А затем создайте 2 подкласса

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 */
    }
}

Теперь общая логика упакована в PaginationWrapper, но фактическая логика базы данных теперь находится в конкретном подклассе.

Именно к такому выводу я пришел. Попробовал код, работает. :-)

Fab Sanchez 18.02.2019 16:54

Другие вопросы по теме