Слайд 2
Параметризированные типы
Параметризированные (generic) типы - классы, интерфейсы и
методы, в которых тип обрабатываемых данных задается как параметр
(параметр типа) .
Параметризированные типы, позволяют использовать более гибкую и в то же время достаточно строгую
типизацию, обеспечивая безопасность типов
Ограничение типа, применение метасимволов
Настраиваемые методы, интерфейсы иерархии классов
Параметры типа, параметризированные классы
Реализация настраиваемых типов, ограничения по применению
Слайд 3
Параметризированные типы
Применение параметризированного класса:
Gen iob = new
Gen(88) ;
Полная идентичность
аргументов типа
Классы, использующие параметр типа, являются настраиваемыми
классами или
параметризованными типами
Слайд 4
Параметризированные типы
Аргумент типа, задаваемый при объявлении параметризированного типа
– может быть только классом, а не примитивным типом
!!!
Разные аргументы:
Gen iob = new Gen(88) ;
Gen strOb = new Gen ("Generics Test");
iob = strOb; // Неверно - разные типы !!!
Gen s =
new Gen(777) ; ./* Неверно - разные типы !!!
т.е. ссылка на одну конкретную версию обобщенного типа несовместима с другой версией того же самого обобщенного типа. */
Слайд 5
Параметризированные типы
Пример1: Параметризированный класс
с одним параметром типа:
package chapt03;
public class Optional
{
private T value;
public Optional() {
}
public Optional(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public void setValue(T val) {
value = val;
}
public String toString() {
if (value == null) return null;
return value.getClass().getName() + " " + value;
}
}
Слайд 6
Параметризированные типы
Пример1: Параметризированный класс
с одним параметром типа:
package chapt03;
public class Runner {
public
static void main(String[] args) {
//параметризация типом Integer
Optional ob1 =
new Optional();
ob1.setValue(1);
//ob1.setValue("2");// ошибка компиляции: недопустимый тип
int v1 = ob1.getValue();
System.out.println(v1);
//параметризация типом String
Optional ob2 =
new Optional("Java");
String v2 = ob2.getValue();
System.out.println(v2);
//ob1 = ob2; //ошибка компиляции – параметризация не ковариантна
Слайд 7
Параметризированные типы
Пример1: Параметризированный класс
с одним параметром типа:
//параметризация по умолчанию – Object
Optional ob3 = new Optional();
System.out.println(ob3.getValue());
ob3.setValue("Java SE 6");
System.out.println(ob3.toString());/* выводится тип объекта, а не тип
параметризации */
ob3.setValue(71);
System.out.println(ob3.toString());
ob3.setValue(null);
}
}
В результате выполнения этой программы будет выведено:
1
Java
null
java.lang.String Java SE 6
java.lang.Integer 71
Слайд 8
Параметризированные типы
Пример1: Параметризированный класс
с одним параметром типа:
В следующей строке кода:
class Gen { ,
где Т обозначает имя параметра типа.
Это имя используется в качестве заполнителя, вместо которого
в дальнейшем подставляется имя конкретного типа, передаваемого классу Gen при создании объекта.
Обозначение Т применяется в классе Gen всякий раз, когда требуется параметр типа.
Всякий раз. когда объявляется параметр типа, он указывается в угловых скобках < >.
Слайд 9
Параметризированные типы
Параметризированный класс
с несколькими параметрами типа:
// Два
параметра типа задаются списком через запятую
class TwoGen {
Т ob1;
V ob2;
TwoGen(Т o1, V о2) { // конструктор
оb1 = o1;
оb2 = о2;
}
// Использование класса
TwoGen tgObn =
new TwoGen (88, "Generics");
Слайд 10
Параметризированные типы
Ограничения на типы, передаваемые параметру типа:
В качестве
верхней границы задается суперкласс, от которого должны быть унаследованы
все аргументы типа:
Gen <Т extends superclass>
Gen <Т extends Number>
Аргументы параметра типа в этом случае:
только тип Number или его подклассы
Integer, Float
Слайд 11
Параметризированные типы
Применение метасимвольных аргументов
необходимо в случае, если
параметр типа невозможно определить
Метасимвол: ?
Слайд 12
Параметризированные типы
Пример
class Stats {
Т[] nums;
Stats(T[] о) {
nums = о;
}
// Вычисляет среднее арифметич. элементов массива
double average() {
double sum = 0.0;
for (int i=0; i < nums.length; i++)
sum += nums[i].doubleValue(); // метод кл. Number – приводит к
// типу Double
return sum / nums.length;
}
}
Слайд 13
Параметризированные типы
Пример (продолжение)
boolean sameAvg(Stats ob) {
// любой объект типа Stats,
// если
Т, то ожидается тип передаваемый вызывающим объектом
if (average() == ob.average())
return true;
else
return false;
}
. . .
Integer inums[] = { 1, 2, 3, 4, 5 };
Double dnums[] = { 1.1, 2.2, 3.3, 4.4, 5.5 };
Stats iob = new Stats(inums);
Stats dob = new Stats(dnums);
System.out.print("Средние арифметические iob и dob ");
if (iob. sameAvg (dob) ) // вызывающий об. и параметр –
// объекты одного класса
System.out.println("совпадают.");
else
System, out.println("отличаются.");
. . .
Слайд 14
Параметризированные типы
Ограничение метасимвольных аргументов
Задание верхней границы:
- имя класса, который служит верхней границей
Задание нижней
границы:
super subclass>
Допустимые аргументы - суперклассы класса subclass. subclass не является допустимым типом аргумента
Слайд 15
Параметризированные типы
Пример
static void showXYZ(Coords
System.out.println("X Y Z Coordinates:");
for(int i=0; i
< c.coords.length; i++)
System.out.println(c.coords [i].x + " " +
с.coords[i].у + " " +
с.coords[i].z);
System.out.println();
}
Слайд 16
Параметризированные типы
Параметризированные методы
могут иметь один или несколько собственных
параметров типа
могут создаваться и внутри непараметризированного класса
могут быть как
статическими, так и нестатическими
Синтаксис записи
<список_парам._типа> возвр._знач.
имя_метода(список_парам.) { ...}
Пример:
static <Т, V extends Т> boolean isIn(T х, V[] у) {
Слайд 17
Параметризированные типы
Пример:
// Параметризированный метод
static boolean isIn(T х, V[]
у) {
for(int i=0; i < y.length; i++)
if(x.equals(y[i])) return true;
return false;
}
// Вызов метода
public static void main(String args[]) {
Integer nums[] = { 1, 2, 3, 4, 5 };
if(isIn(2, nums))
System.out.println("2 содержится в массиве");
}
Слайд 18
Параметризированные типы
Пример:
class GenCons {
private double
val;
GenCons(T arg) { //
Параметризированный только метод
val = arg.doubleValue();
}
void showval() {
System.out.println("val: " + val);
}
}
class GenConsDemo {
public static void main(String args[]) {
GenCons test = new GenCons(100);
GenCons test2 = new GenCons(123.5F);
test.showval();
test2.showval();
}
}
Вывод программы:
val: 100,0
val: 123,5
Слайд 19
Параметризированные типы
Настраиваемые интерфейсы
задаются так же, как настраиваемые
классы
interface MinMax {
класс, реализующий
интерфейс
Class MyClass
>
implements MinMax {
Не повторяется
Та же граница
Слайд 20
Параметризированные типы
Иерархии параметризированных классов
параметризированный класс может быть суперклассом
или быть подклассом
аргументы типа, необходимые суперклассу, должны передаваться всем
подклассам !!!
class Gen {
T ob;
Gen(T o) {
ob = o;
}
T getob() {
return ob;
}
}
class Gen2 extends Gen{
Gen2(T o) {
super(o); // передача суперклассу
}
}
…
Gen2 x = new Gen2(108);
System.out.print(x.getob());
Слайд 21
Параметризированные типы
Иерархии настраиваемых классов (продолжение)
в подклассе всегда определяются
параметры типа, требующиеся для его настраиваемого суперкласса
подкласс может иметь
собственные параметры типа
class Gen2 extends Gen {
V оb2;
Gen2(T о, V o2) {
super(o); // передача аргумента типа // конструктору супертипа
ob2 = o2;
}
}
Слайд 22
Параметризированные типы
Применение настраиваемых типов в коллекциях
все классы и
интерфейсы, связанные с классами АrrayList, LinkedList и TreeSet -
параметризированные:
ArrayList
list = new ArrayList();
преимущества:
гарантируется сохранение в коллекции ссылок на объекты только нужного типа
исключается необходимость явного приведения типа ссылки, при извлечении из коллекции
Слайд 23
Параметризированные типы
Сравнение типов настраиваемой иерахии:
операция
объект instanceof
тип
возвращает true, если объект имеет заданный тип или
м.б. преобразован к нему
if (iOb instanceof Gen2>)
System.out.println("iOb совместим с Gen2");
Приведение типов: преобразование одного экземпляра параметризированного класса в другой
(Gen
) iob2
если они взаимно совместимы
Слайд 24
Параметризированные типы
Реализация в Java обобщенных типов
При компиляции:
информация о
обобщенных типах удаляется
(эффект стирания)
параметры типа
заменяются ограничивающими их типами (если заданы) либо Object
все параметризованные классы используют один класс:
Gen iOb = new Gen(99);
Gen fOb = new Gen(102.2F);
Systern.out.println(iOb.getclass () .getName()) ;
System, out.println(fOb.getClass (). getName());
Результат:
Gen
Gen
Слайд 25
Параметризированные типы
Поэтому нельзя: запрашивать тип в процессе выполнения
программы
public class MyList {
public E[] toArray() {
return new E[5]; // compile error
}
public boolean canAdd(Object o) {
return (o instanceof E); // compile error –}
public E convertToE(Object o) {
return (E) o; // compile warning, unchecked cast
}
}
Слайд 26
Параметризированные типы
Raw Type
Можно создать объект настраиваемого (генефицированного) класса
без указания типов аргументов
Классы Pre-J2SE 5.0 продолжают функционировать под
J2SE 5.0 JVM как raw тип
// ??????
List
ls = new LinkedList();
// Raw type
List lraw = new LinkedList();
Слайд 27
Параметризированные типы
Ограничения
T t = new T();
// конструктор ?
Статические члены класса не могут использовать
параметры типа
static T t; //??????
Слайд 28
Параметризированные типы
Ограничения (продолжение)
Создание экземпляров универсальных типов
class Test
{
T values;
//ok
Test(T[] n) {
values = new T[10]; // базовый тип - параметр типа
values = n; //ok
}
}
Массивы
Test
iTest[] = new Test[10] // нельзя объявлять с аргументами типа
Test> iTest[] = new Test>[10] //ok