Generics - это подход к реализации класса, который позволяет использовать его с различными типами данных без изменения его реализации.
Ранее решалось через Object класс, но новый подход добавляет, проверку в местах где мы ждем определенные типы на соответствие этим типа. А также будет автокаст к указанному типу.
При сравнении Set<String> и Set<Integer> будет true. Тк. type erasure при компиляции заменить все на Object.
Но List<String> не является наследником List<Object> - Инвариантность.
List<String> strings = new ArrayList<String>(); // ошибка компиляции! List<Object> objects = strings;
Для метода необязательно использовать указание типа.
public <T> void f(T x) { System.out.println(x); } public static void main(String[] args) { Main main = new Main(); main.f(2); }
Но можно и указать
main.<Integer>f(2);
Используется для создания ковариантности и контравариантности. Тк по умолчанию generics инвариантны.
И стирания типа при компиляции будет до указанного класса, а не до Object.
<T extend Animal>
И стирания типа при компиляции будет до Object.
<? super Animal>
public void print(List<? super Integer> list) // OK //but you can't use type parameter: public <T super Integer> void print(List<T> list) // Won't compile
Multiple bounds - возможность добавлять несколько ограничений.
<T extends B1 & B2 & B3>
WildCard обозначается знаком "?". Необходим когда мы не будем указывать тип generic вручную. Но мы не можем создавать связь между указанным типом в реализации.
Пример с типизацией: public static <T extends Number> void copy(List<T> dest, List<T> src) Пример с WildCard: public static void copy(List<? extends Number> dest, List<? extends Number> src)
? and ? extends Object - это одно и тоже.
WildCard не поддерживает "multiple bounds".
>PECS - правило при использовании WILDCARD c коллекциями. Позволяет добавить Ковариантность или Контравариантность в коллекции.
Пример с extend: если мы указали <? extends Number> - означает то что мы возьмем, будет наследоваться от Number и мы знаем как с этим работать. Мы не можем в него класть так как мы не знаем какой конкретно тип там есть.
Пример с super: если мы указали <? super Number> - означает то что мы возьмем, будет: Number или Object. Мы не можем брать не зная конкретный тип. Но мы можем в него класть как Object.
public void sendEmailsFixed(List<? extends User> users) {} List<Customer> customers = Arrays.asList(new Customer("john"), new Customer("arys")); sendEmailsFixed(customers);
private void addUsersFromMarketingDepartmentFixed(List<? super Operator> users) { users.add(new Operator("john doe"));