Я добавляю 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();
}
}
Зачем вообще использовать дженерики? На мой взгляд, не имеет особого смысла. Поскольку вы могли бы просто вызвать конкретный метод напрямую




Вы можете сделать этот класс абстрактным, а затем подкласс должен реализовать фактический вызов базы данных:
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, но фактическая логика базы данных теперь находится в конкретном подклассе.
Именно к такому выводу я пришел. Попробовал код, работает. :-)
Если вы выполняете нетривиальное приведение, то следует отметить идущий. Такие гипсы по своей сути небезопасны.