Слайд 1 Мультимедийный курс
Программирование на Java
Лекция 6.1
Параметризированные типы
(Обобщения, Generics)
Слайд 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Параметризированные типы
Ограничение метасимвольных аргументов
Задание верхней границы:
класса, который служит верхней границей
Задание нижней границы:
Допустимые аргументы - суперклассы класса subclass. subclass не является допустимым типом аргумента
Слайд 15Параметризированные типы
Пример
static void showXYZ(Coords
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
V extends Т> 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
Comparable
>
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
Слайд 29Параметризированные типы
Ограничения (продолжение)
Исключения
Невозможно
сгенерировать или перехватить исключение, описываемое универсальным объектом
создать
параметризированный класс, расширяющий класс Throwable
использовать параметр типа в выражении
catch
Допустимо использовать параметр типа в выражении throws