upper-bound - List<? extends Number>. Любой наследник, а так же сам целевой тип. Для данного типа (де-факто) запрещена любая вставка (кроме null) - для вставки используется List<? super Number>. При этом, первичная вставка допускается:
lower-bound - List<? super Number>. Любой класс, от которого целевой наследуется, или сам целевой. Данный вид wildcard не может быть использован в методе. Вставка доступна, а получение - доступно только с принудительным преобразованием:
Если объект, или массив объектов, или какой-то типа данных может быть применен к другому (родительскому) типу, то это называется ковариантность:
1 2 3
String[] a = {"a", "b", "c"}; Object[] b = a; b[0] = 123; // ошибка ArrayStoreException;
PECS (Producer Extends Consumer Super)
Был описан выше, но для повторения:
если <? extends ...> - это только чтение (Producer); для коллекций он ничего в себя не принимает, только отдает;
если <? super ...> - это только хранение (Consumer); в случае коллекций он только принимает и ничего не отдает.
Важно! В случае unbound, это де-факто <? extends Object>, а значит допускается только чтение! Если предполагается и читать и записывать, лучше не использовать wildcards.
Переменные типа
1
public <T extendsComparable<T>> T method(...) { ... }
В примере выше присутствует конструкция, называемая, recursive bound - т.е. когда при определении Generic где-то в нем используется целевой класс - т.е. в нашем случае T используется в Comparable<T>. Это действие ограничено только правилами наследования. Так же, в примере выше нельзя использовать <T super ...>.
Multiple bound
Множественные ограничения, которые накладывают дополнительные ограничения на тип:
1
public <T extendsString & Comparable<? super T>> T method(...) {...}
Важно! Второй и последующими границами могут быть только интерфейсы. Например:
1
public <T extendsNumber & Comparable<T> & CharSequence>voidtest(T item)
Type erasure
В действительности, никаких типизаций не существует в скомпилированном коде - компилятор перед использованием Generic типа выполняет принудительный type-cast:
1 2
List<String> list = ...; Strings= (String) list.get(0); // в коде: list.get(0);
В таком случае могут возникать непредвиденные ситуации:
В примере выше, компилятор из метода 1 создает фоновый метод compareTo(Object), который мы пытаемся создать. И поскольку фоновый и созданный имеют одинаковую сигнатуру, они будут друг с другом конфликтовать.
Причем, если порядок определения методов будет соответствовать указанному выше, ошибка будет при определении класса с указанием дубликата метода compareTo. Если дефиницию методов поменять местами, то ошибка будет на первом методе (с сигнатурой Object), сигнализирующая о дублировании метода compareTo.
Method ref.
Используется, как правило, в функциональных интерфейсах как средство для быстрого вызова метода без загромождения кода. Существует 4 вида ссылок на методы:
Статические. Передача параметра осуществляется в целевой статический метод класса.