
- •JAVA-ТЕХНОЛОГИЯ
- •Java generics:
- •Ограничения на тип-параметр
- •Пример: параметризованный тип с ограничениями и его реализация
- •Пояснения к примеру
- •Реализация примера Stack
- •Пояснения к байт-коду метода main
- •Байт-код методов класса Stack
- •Пояснения к байт-коду метода push
- •Параметризация и подтипы
- •Фрагмент примера Stack
- •Шаблоны (wildcards)
- •Шаблоны с ограничениями – bounded wildcards
- •Аннотации (annotations)
- •Аннотации в Java 1.5
- •Аннотации в Java 1.5 (продолжение)
- •Аннотации в Java 1.5: общие правила

JAVA-ТЕХНОЛОГИЯ
Сафонов Владимир Олегович
Профессор кафедры информатики, руководитель лаборатории Java- технологии (http://polyhimnie.math.spbu.ru/jtl)
Email: vosafonov@gmail.com
Лекция 14

Java generics:
Различные параметризованные типы разделяют один и тот же класс
Пример (Sun) :
Vector<String> x = new Vector<String>(); Vector<Integer> y = new Vector<Integer>(); boolean b = x.getClass() == y.getClass();
Вданном примере значение булевской переменной b – истина, так как различные типы
Vector<String> и Vector<Integer> разделяют один и тот же класс Vector во время выполнения
(C)В.О. Сафонов.
2013

Ограничения на тип-параметр
<T extends C1 & … & Cn>
T – тип-параметр
C1, … Cn – имена классов или интерфейсов
Ограничения задают требуемое поведение типа-параметра, т.е. набор его операций (методов), который может использоваться при реализации типа, параметризуемого типом T
T – типовая переменная (type variable)
Вариант без ограничений: < T >
(C) В.О. Сафонов. 2013

Пример: параметризованный тип с ограничениями и его реализация
package generics_test;
public class Main {
public static class Stack <T extends Comparable<T> & java.io.Serializable> { public void push (T x) {
int i = x.compareTo(x); System.out.println("i=" + i);
}
public T pop () { return null; }
}
public Main() { }
public static void main(String[] args) {
Stack <String> s = new Stack <String>();
// Stack <Integer> I = s; -- ошибка: incompatible types s.push("abc");
}
}(C) В.О. Сафонов. 2013

Пояснения к примеру
Определяется параметризованный тип Stack
Ограничения на тип-параметр: он должен реализовывать два интерфейса:
- параметризованный интерфейс Comparable<T>, содержащий единственный метод:
int compareTo(T obj)
Предполагаемая семантика метода:
результат операции t1.compareTo(t2) < 0, если t1 “меньше” t2;
== 0, если t1 “равно” t2; > 0, если t1 “больше” t2 Может использоваться, например, при сортировке
- интерфейс-маркер Serializable, т.е. быть сериализуемым
Все параметризации класса Stack разделяют этот класс (он существует в единственном экземпляре и не “размножается”, как template C++, при каждой параметризации). Но, например,
Stack<String> и Stack<Integer> - несовместимые типы
(C) В.О. Сафонов. 2013

Реализация примера Stack
(байт-код получен инструментом jclasslib 3.0 фирмы ej-technologies GMbH)
Компилятор генерирует два класс-файла: Main.class и Main$Stack.class
Байт-код метода main:
0 new #2 <generics_test/Main$Stack>
3 dup
4 invokespecial #3 <generics_test/Main$Stack.<init>>
7 astore_1
8 aload_1
9 ldc #4 <abc>
11 invokevirtual #5 <generics_test/Main$Stack.push>
14return
(C)В.О. Сафонов. 2013

Пояснения к байт-коду метода main
#2, #3, … - ссылки на константный пул (в нем размещаются константы, и типы, и т.д.)
Invokespecial, invokevirtual – формы вызова метода
aload_1, astore_1 – команды загрузки в стек значения локальной переменной номер 1 и записи содержимого вершины стека в локальную переменную номер 1. Локальные переменные нумеруются; номер 0 занят параметром args
ldc – загрузка в стек константы (строки)
Содержательно байт-код ничем не отличается от байт-кода без использования
(C) В.О.параметризованныхС фонов. типов
2013

Байт-код методов класса Stack
Метод push:
0 aload_1
1 aload_1
2 invokeinterface #2 <java/lang/Comparable.compareTo> count 2
7 istore_2
8 getstatic #3 <java/lang/System.out>
11 new #4 <java/lang/StringBuilder>
14dup
15invokespecial #5 <java/lang/StringBuilder.<init>>
18ldc #6 <i=>
20invokevirtual #7 <java/lang/StringBuilder.append>
23iload_2
24invokevirtual #8 <java/lang/StringBuilder.append>
27invokevirtual #9 <java/lang/StringBuilder.toString>
30invokevirtual #10 <java/io/PrintStream.println>
33return
(C)В.О. Сафонов. 2013

Пояснения к байт-коду метода push
Идея реализации обращения к операциям типа- параметра T: благодаря объектно-ориентированной природе Java, в частности, понятию интерфейса и
реализации интерфейса, необходимые операции берутся из типа аргумента x
Фактический тип аргумента x (String) имеет свою VMT
(virtual method table), в которой, в частности, содержится метод compareTo. Команда invokeinterface
вызывает этот метод
Благодаря VMT, нет необходимости в явной передаче указателя на метод compareTo в качестве дополнительного аргумента
Вывод значения i: для оптимизации (во избежание образования мусора) вместо класса String используется
класс StringBuilder
(C) В.О. Сафонов.
2013Проблема такой реализации: “type erasure” (стирание

Параметризация и подтипы
Если: класс S – подкласс класса C: public class S extends C { … }, G – параметризованный тип: public class G<T>,
то G<S> - НЕ подтип типа G<C>, т.е. присваивания: p: G<C>; q: G<S>; p = q; q = p;
-ОШИБОЧНЫ (несовместимость типов)
Аналогично, если G1 – подкласс класса G:
public class G1<T> extends G<T> { … }
то типы G1<C> и G<C> также НЕСОВМЕСТИМЫ: r: G1<C>; s: G<C>; r = s; s = r; - ОШИБОЧНЫ
Пример (G.Bracha, Sun) : Если Driver – подкласс класса Person, то List <Driver> - НЕ подкласс класса List <Person>:
список водителей не может рассматриваться как список людей, иначе в этот список могут быть внесены новые люди, не имеющие водительских прав
(C) В.О. Сафонов. 2013