Добавил:
Rumpelstilzchen2018@yandex.ru Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

3-й семестр / Лекции / 6 - Презентация 2 - Дженерики, Абстрактные типы данных, Стек

.pdf
Скачиваний:
57
Добавлен:
25.12.2020
Размер:
879.76 Кб
Скачать

Центр дистанционного обучения

Generics

Объявление class AnyList<E>” – это объявление “заготовки” типа, а конкретный тип AnyList<Integer> устанавливает параметр E=Integer. Поэтому метод get для AnyList<Integer>

возвращает тип Integer.

Синтаксически это похоже на C++ templates, но реализовано по-другому, что имеет последствия при использовании generics в программах.

online.mirea.ru

Центр дистанционного обучения

Generics – type erasure

Пример:

public class AnyBox<E> { private E value = null;

public E get() { return value; }

public void set(E newValue) { value = newValue; }

}

online.mirea.ru

Центр дистанционного обучения

Generics – type erasure

public class AnyBox<E> { private E value = null; public E get() {

return value;

}

public void set(E newValue) {

value = newValue;

}

}

AnyBox<String> box = new AnyBox<>();

box.set(“Some string”);

String boxValue = box.get();

public class AnyBox {

private Object value = null; public Object get() {

return value;

}

public void set(Object newValue) {

value = newValue;

}

}

AnyBox box = new AnyBox(); box.set(“Some string”);

String boxValue = (String) box.get();

//Здесь система типов гарантирует,

//что ClassCastException не произойдет

//(но см. ссылку)

online.mirea.ru

Центр дистанционного обучения

Generics – type erasure

Таким образом, класс AnyBox существует в единственном экземпляре, AnyBox<String> и AnyBox<Integer> при выполнении программы являются одним и тем же классом AnyBox (который называется raw class). Одно из следствий:

public class AnyBox<E> { void set(E newValue);

void set(Object newObject);

}

не скомпилируется, т.к. в raw-классе эти методы будут иметь одну и ту же сигнатуру.

online.mirea.ru

Центр дистанционного обучения

Generics – type erasure

Другие ограничения, вызванные type erasure:

нельзя написать new E() (потому что это было бы транслировано в new Object())

нельзя написать new E[size] (потому что это было бы транслировано в new Object[size])

Типовые параметры существуют исключительно во время компиляции программы.

online.mirea.ru

Центр дистанционного обучения

Generics – type erasure

Методы тоже могут быть generic:

public class BoxUtil { // класс – не generic

static <E> void clear(AnyBox<E> box) {

box.set(null);

}

}

AnyBox<String> box = ...;

// обычно компилятор определяет параметр E автоматически:

BoxUtil.clear(box);

// Но если нужно, можно указать вручную:

BoxUtil.<String>clear(box);

online.mirea.ru

Центр дистанционного обучения

Generics – type erasure

Для типовых параметров могут быть указаны ограничения:

public class BoxUtil {

static <E extends Runnable> void runBox(AnyBox<E> box) {

E runnable = box.get(); // гарантируется, что E наследуется от Runnable

runnable.run();

}

}

BoxUtil.runBox(new AnyBox<String>()); // ошибка, String – не Runnable

BoxUtil.runBox(new AnyBox<Runnable>()); // компилируется

online.mirea.ru

Центр дистанционного обучения

Generics – type erasure

Иногда нам не важно значение типового параметра (wildcard):

public class BoxUtil {

static void clearBox(AnyBox<?> box) {

box.set(null);

}

}

BoxUtil.clearBox(new AnyBox<String>());

BoxUtil.clearBox(new AnyBox<Integer>());

online.mirea.ru

Центр дистанционного обучения

Generics – type erasure

Для ? тоже могут быть указаны ограничения:

public class BoxUtil {

static void runBox(AnyBox<? extends Runnable> box) {

Runnable runnable = box.get();

runnable.run();

}

}

BoxUtil.runBox(new AnyBox<String>()); // ошибка, String – не Runnable

BoxUtil.runBox(new AnyBox<Runnable>()); // компилируется

online.mirea.ru

Центр дистанционного обучения

Generics – type erasure

public class BoxUtil {

static <E> void copyBox(AnyBox<E> to, AnyBox<E> from) {

E value = from.get();

to.set(value);

}

}

AnyBox<String> to = new AnyBox<>();

AnyBox<String> from = new AnyBox<>();

// здесь важно, что у to и from один и тот же параметр E:

BoxUtil.copyBox(to, from);

online.mirea.ru