Дженерики
© |
NetCracker Technology Corp. |
/ |
[Тёмная и безрадостная] жизнь до дженериков
.
Основным способом писать код, не зависящий от типов, было написание кода, работающего с Object.
Например, абстракция списка реализовывалась примерно следующим образом:
public interface List { Object get(int index); void add(Object element);
}
Использование такого списка:
List list = new ListImpl(); list.add(”string”);
// ...
Object obj = list.get( );
String str = (String) obj; // Явное преобразование типа
System.out.println(str.substring( , str.length()- ));
.
© |
NetCracker Technology Corp. |
/ |
[Тёмная и безрадостная] жизнь до дженериков
.
Делать явные касты было очень неудобно и чревато ошибками времени выполнения:
List list = new ListImpl(); list.add(”string”);
// ...
Object obj = list.get( );
// Забыли, что list состоит из строк
Integer integer = (Integer) obj; // FFFFUUUUUU~~~ System.out.println(integer.intValue() + );
Поэтому для безопасности тип проверяли явно:
Object obj = list.get( ); if (obj instanceof String) {
String str = (String) obj; // Опять явное преобразование типа
System.out.println(str.substring( , str.length()- ));
}else {
//сделать что-то ещё
.Очень неудобно, некрасиво и гора потенциальных ошибок в наличии.
© |
NetCracker Technology Corp. |
/ |
Появление дженериков
.
ВJava . ( год) была добавлена возможность т.н. обобщённого програмирования, включающая в себя поддержку обобщённых классов
(generic classes) и обобщённых методов (generic methods).
Впервую очередь дженерики были нужны для создания типобезопасной библиотеки коллекций, т.е. с проверкой типов на этапе компиляции, а не в рантайме.
Сейчас дженерики используются в большом числе библиотек самого разного назначения, но с одной целью — обеспечением правильности работы с типами.
.
© |
NetCracker Technology Corp. |
/ |
[Светлая и радостная] жизнь с дженериками
.
Интерфейс списка с применением дженериков:
public interface List<T> { T get(int index);
void add(T object);
}
.
© |
NetCracker Technology Corp. |
/ |
[Светлая и радостная] жизнь с дженериками
.
Интерфейс списка с применением дженериков:
public interface List<T> { T get(int index);
void add(T object);
}
Его использование:
List<String> list = new ListImpl<String>();
// WTF, два раза String? Компилятор настолько тупой?
.
© |
NetCracker Technology Corp. |
/ |
[Светлая и радостная] жизнь с дженериками
.
Интерфейс списка с применением дженериков:
public interface List<T> { T get(int index);
void add(T object);
}
Его использование:
// С версии Java можно так:
List<String> list = new ListImpl<>(); list.add(”string”);
// ...
String str = list.get( ); // Никаких явных преобразований типов!
System.out.println(str.substring( , str.length()- ));
.
© |
NetCracker Technology Corp. |
/ |
[Светлая и радостная] жизнь с дженериками
.
Интерфейс списка с применением дженериков:
public interface List<T> { T get(int index);
void add(T object);
}
Его использование:
// С версии Java можно так:
List<String> list = new ListImpl<>(); list.add(”string”);
// ...
String str = list.get( ); // Никаких явных преобразований типов!
System.out.println(str.substring( , str.length()- ));
Теперь компилятор выдаст ошибку, если бы попытаемся взять из списка не тот тип:
Integer integer = list.get( ); // Ошибка компиляции
System.out.println(integer + );
.
© |
NetCracker Technology Corp. |
/ |
Виды дженериков
.
В языке присутствует два вида дженериков:
. обобщённые классы:
public interface List<T> { void add(T element);
T get(int index);
}
.
© |
NetCracker Technology Corp. |
/ |
Виды дженериков
.
В языке присутствует два вида дженериков:
. обобщённые классы:
public interface List<T> { void add(T element);
T get(int index);
}
. обобщённые методы:
public final class Collections { private Collections() {}
public static <T> List<T> emptyList() { ... }
public static <T> List<T> unmodifiableList(List<T> input) { ... }
}
обобщённые методы могут быть и нестатическими.
.
© |
NetCracker Technology Corp. |
/ |