T[] array = new T[size]
-Создание массива конкретного типа:
Type<Integer> arr = new Type<Integer>[10];
Применение параметризованных типов в классах
class Name <T,E> { private T t; private E e;
public Name(T t, E e) { this.t = t; this.e = e;
}
public T getT() { return t; }
public void setE(E e) { this.e = e;}
}
class test {
public static void main(String[] args){ Name<String, Integer> obj1 = new Name<String,
Integer>("string", 3);
String a = obj1.getA(); obj1.setB(10);
Name obj2 = new Name(3, new ArrayList(3)); Integer i = (Integer)obj2.getA();
}
}
Особенности параметризованных типов
Тип можно указывать не только для классов и интерфейсов, но и методов и конструкторов (не зависимо от того, параметризирован класс и интерфейс или нет. В этом случае тип указывается перед возвращаемым значением. При использовании одинаковых идентификаторов типа у класса и у метода или конструктора, тип последних скрывает тип класса (интерфейса).
Простые параметризованные типы в методах и конструкторах
interface GIN <T> {
<T> void meth1 (T t); //Тип-параметрметода скрыватинтпетрфейса
<E> E meth2 (E e); |
//Уметодасвойтип |
- |
параметр |
//Методиспользуеттип |
|
T meth3 (T t); |
||
интерфейса |
|
|
} |
|
|
class GCL<T> implements GIN<T> { |
|
|
T t; |
} |
//Конструктор |
public <T> GCL(T t){ |
||
скрывтипклаетсса |
|
} //У |
public <E> GCL (E e, T t) { |
||
конствойруктораионп |
|
|
//используеттипкласса
@Override
public <T1> void meth1(T1 t1) { } //реализация методабезпутаницы //сименами типов-параметров
@Override
public <E> E meth2(E e) {return e; } @Override
public T meth3(T t) {return null;}
}
Если информация о типе стирается, как вызвать определенный метод у объекта имеющего тип – параметр?
class GenericSpeaker<T> { T source;
public void giveVoice() { //sourceошибкакомпиляции.say();
}
}
Ограниченные типы
interface Speaker { void say()
}
class Cat implements Speaker{ public void say() {
System.out.println("maaauuuu"); }
}
class GenericSpeaker<T extends Speaker> { T source;
public void giveVoice() { source.say();
}}
Ограничение типа позволяет использовать у ссылок методы и поля, доступные в типе-ограничителе. Типы, не наследующие от указанного, не могут быть использованы при создании объектов.
Class Name<T extends ClassName &
Interface1 & Interface2 & … > {...}
Как имя типа может быть указан 1 класс и множество интерфейсов, разделенных &. Как имя типа может быть указан ранее введенный параметр.
class GenericClass<T extends Comparable<T>> {...}
Маски
Что делать при передаче экземпляров параметризованных типов в методы, т.е. как писать сигнатуру? Для этого используется маска <?>, обозначающая произвольный тип-параметр.
class Generic<T> {
...
boolean compare(Generic<?> o) { return o.getObj() == obj;
}
Запись: boolean compare(Generic<?> o) {…}
означает, что в качестве параметра методу compare может быть передан тип Generic, параметризированный любым (а не конкретным, как если бы было Generic<T>) типом.
isEqual = ccompare(Generic<Runnable> o); isEqual = compare(Generic<StringBuilder> o); isEqual = compare(Generic<Calendar> o);
isEqual = compare(Generic<K> o); ompare(Generic<Integer> o); isEqual =
Маски позволяют задать отношение между параметризированными типами, а не типами-параметрами.
//пустьестьиерархия |
(рисунок7.2) |
||
class Fruit |
{} |
|
|
class Apple |
extends Fruit{} |
||
class |
Citrus extends Fruit{} |
||
class |
Orange extends Citrus{} |
||
Рисунок 8.2 – Иерархия классов
List<?> fruits = new ArrayList<Fruit>(); //Всем тоды add неработаютсошибкойкомпиляции
//add(capture<?>) в List неможетбытьпримененк
<Типдобавляемогообъекта > fruits.add(new Object());
fruits.add(new Fruit()); fruits.add(new Apple()); fruits.add(new Citrus()); fruits.add(new Orange());
//Этотмеработаетод |
|
|
Object o = fruits.get(0); |
get |
|
//Остальныеметоды |
get неработают,потомучто |
|
возвращает Object инужноприводитьбъектунужному типу
Fruit f = fruits.get(0); Apple a = fruits.get(0);
Citrus c = fruits.get(0); Orange or = fruits.get(0); \\Методкомпилируется
public static List<?> getList() { List<Fruit> fruits = new ArrayList<Fruit>(); fruits.add(new Apple());
return fruits;
}
List<?> wFruits1 = getList(); \\Работает List<Fruit> wFruits2 = getList(); \\Ошибка компиляции
List<Apple> wFruits3 = getList(); \\Ошибка компиляции
public static void addToList(List<?> fruits) { \\add не работают все
fruits.add(new Fruit()); fruits.add(new Apple()); fruits.add(new Citrus()); fruits.add(new Orange());
Object o = fruits.get(0); \\работает
\\остальные get неработают
Fruit f = fruits.get(0); Citrus c = fruits.get(0); Orange or = fruits.get(0);
}
//всевызовыневызываютошибкикомпиляции
addToList(new ArrayList<Fruit>()); addToList(new ArrayList<Apple>()); addToList(new ArrayList<Citrus>()); addToList(new ArrayList());
Ограничение сверху Определяет отношение восходящего преобразования:
<? extends super>
Некоторый конкретный тип, параметр которого наследуется от super.