Тонкости и особенности дженериков
© |
NetCracker Technology Corp. |
/ |
Сырые типы
.
Дженерики появились в Java . ( год). Но до этого уже было колоссальное количество кода на Java — без дженериков.
Для сохранения обратной совместимости есть возможность использовать обобщённые типы без указания типовых параметров:
List list = new List(); list.add(”abcd”); list.add( );
Обобщённые типы, употреблённые без параметров, называются сырыми
(raw).
Отличие от List<Object> и List<?> — в вариантности и безопасности:
List<String> strings = new ArrayList<>();
List<Object> objects = strings; // Ошибка компиляции
.
© |
NetCracker Technology Corp. |
/ |
Сырые типы
.
Дженерики появились в Java . ( год). Но до этого уже было колоссальное количество кода на Java — без дженериков.
Для сохранения обратной совместимости есть возможность использовать обобщённые типы без указания типовых параметров:
List list = new List(); list.add(”abcd”); list.add( );
Обобщённые типы, употреблённые без параметров, называются сырыми
(raw).
Отличие от List<Object> и List<?> — в вариантности и безопасности:
List<String> |
strings |
= |
new ArrayList<>(); |
List<Object> |
objects |
= |
strings; // Ошибка компиляции |
List raw = strings; |
// Всё ОК |
.
© |
NetCracker Technology Corp. |
/ |
Сырые типы
.
Дженерики появились в Java . ( год). Но до этого уже было колоссальное количество кода на Java — без дженериков.
Для сохранения обратной совместимости есть возможность использовать обобщённые типы без указания типовых параметров:
List list = new List(); list.add(”abcd”); list.add( );
Обобщённые типы, употреблённые без параметров, называются сырыми
(raw).
Отличие от List<Object> и List<?> — в вариантности и безопасности:
List<String> |
strings |
= |
new ArrayList<>(); |
List<Object> |
objects |
= |
strings; // Ошибка компиляции |
List raw = strings; |
// Всё ОК |
List<?> wildcard = string; // Тоже ОК, но...
.
© NetCracker Technology Corp. /
Сырые типы
.
Дженерики появились в Java . ( год). Но до этого уже было колоссальное количество кода на Java — без дженериков.
Для сохранения обратной совместимости есть возможность использовать обобщённые типы без указания типовых параметров:
List list = new List(); list.add(”abcd”); list.add( );
Обобщённые типы, употреблённые без параметров, называются сырыми
(raw).
Отличие от List<Object> и List<?> — в вариантности и безопасности:
List<String> strings |
= new ArrayList<>(); |
||
List<Object> objects |
= strings; |
// Ошибка компиляции |
|
List raw = strings; |
// Всё ОК |
|
|
List<?> wildcard = string; // Тоже ОК, но... |
|||
wildcard.add(”abcd”); |
// ...ошибка компиляции |
||
. |
|
|
|
© |
NetCracker Technology Corp. |
/ |
Сырые типы
.
Сырые типы порождают предупреждения компилятора.
Вместо сырых типов всегда следует использовать либо wildcard’ы, либо параметр <Object>.
Единственное исключение — взаимодействие со старым унаследованным кодом. К сожалению, такое до сих пор встречается (а дженерикам уже скоро лет!).
.
© |
NetCracker Technology Corp. |
/ |
Внутреннее устройство дженериков
.
Дженерики существуют только на этапе компиляции.
Было:
public class TrivialComparator<T extends Comparable<T>> implements Comparator<T> {
@Override public int compare(T left, T right) { return left.compareTo(right);
}
}
public static <T> void add(Collection<? super T> coll, T elem) { ... }
Стало:
public class TrivialComparator implements Comparator {
@Override public int compare(Comparable left, Comparable right) { return left.compareTo(right);
}
}
public static void add(Collection coll, Object elem) { ... }
.
© |
NetCracker Technology Corp. |
/ |
Стирание типов
.
Процесс (и суть) удаления информации об обощённых типах называется
стиранием типов (type erasure).
Следствия стирания типов:
невозможно получить объект класса типа-параметра: T.class;
невозможно перегрузить метод только по типовому параметру:
public void <T> doSomething(List<T> list);
public void doSomething(List<String> list); // Ошибка компиляции
невозможно создать массив из элементов с типом-параметром:
public void <T> makeArray() {
return new T[ ]; // Ошибка компиляции
}
.
© |
NetCracker Technology Corp. |
/ |
Стирание типов
.
Есть хитрость, позволяющая сохранить информацию о типах-параметрах.
// Никакой информации нет
TypeTag<Optional<String>> tag = new TypeTag<Optional<String>>();
.
© |
NetCracker Technology Corp. |
/ |
Стирание типов
.
Есть хитрость, позволяющая сохранить информацию о типах-параметрах.
// Никакой информации нет
TypeTag<Optional<String>> tag = new TypeTag<Optional<String>>();
// А так есть!
TypeTag<Optional<String>> tag = new TypeTag<Optional<String>>() {};
Информация об обощённом типе в анонимном классе доступна через reflection.
.
© |
NetCracker Technology Corp. |
/ |
Что ещё осталось?
.
взаимодействие дженериков и массивов — более подробно;
подробности и правила стирания типов, bridge-методы;
подробности о наследовании, переопределении и перегрузке методов в обобщённых классах;
параметризованные конструкторы (о них вообще никто ничего не знает!);
дженерики и исключения;
подробнее про вывод типов;
захват wildcard’ов;
и т.д....
.
© |
NetCracker Technology Corp. |
/ |
Ссылки
.
Java Generics FAQ: http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
Java Language Specification, . – . , . .
Oracle Java Generics Tutorial: http://docs.oracle.com/javase/tutorial/java/generics/index.html
.
© |
NetCracker Technology Corp. |
/ |