Материал: 8

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

public class GenericClass<T> { private T obj;

public void setObj(T t) {obj = t;} public T getObj() {return obj;} public void print() {

System.out.println(obj);

}

}

Main:

GenericClass<Integer> g = new GenericClass<Integer>();

g.setObj(5); // auto-boxing

int i = g.getObj(); // auto-unboxing g.print();

Пример

class Crossover {} class Garage {

private Crossover parkedAuto;

public Garage(Crossover parkedAuto) { this.parkedAuto = parkedAuto;

}

public Crossover getParkedAuto(){ return parkedAuto;}

}

class Man {

public static void main(String[] args) { Garage garage = new Garage (new

Crossover());

}

}

Проблемы

Обычные классы и методы работаю с конкретными типами (примитивы или классы). Что делать, если нужно работать с разнообразными типами?

Пример иерархии типов

class Auto {}

class Crossover extends Auto{} class Hatchback extends Auto{}

class Garage {

private Auto parkedAuto;

public Garage(AutoконструкторparkedAuto) { // this.parkedAuto = parkedAuto;

}

public Auto getParkedAuto(){ return parkedAuto;}

}

class Main {

public static void main(String[] args) { Garage garage = new Garage (new

Crossover());

Garage anotherGarage = new Garage (new Hatchback());

}

}

Увеличение гибкости за счет наследования

Код работает с объектами по ссылке на базовый тип. Этот код может быть использован для работы с производными типами. Достигаемая гибкость работает только в пределах одной иерархии (наследования).

interface Wheeled{}общийинтерфейс//

class Crossover implements Wheeled{} class Hatchback implements Wheeled{}

class

Trailer

implements Wheeled{}

class

Garage {

 

private Wheeled parkedThing; public Garage(Wheeled

parkedThing){this.parkedThing = parkedThing;} public Wheeled getParkedThing(){ return

parkedThing;}

}

class Main {

public static void main(String[] args) { Garage garage = new Garage (new

Crossover());

Garage anotherGarage = new Garage (new

Trailer());

}

}

Увеличение гибкости за счет интерфейсов

Преимущества:

-код работает с объектами по интерфейсной ссылке;

-этот код может быть использован для работы с любыми объектами, реализующими этот интерфейс;

-более гибкий механизм (по сравнению с наследованием), но требует реализации интерфейса.

interface Wheeled{}

class Crossover implements Wheeled{}

class Hatchback

implements Wheeled{}

class

Trailer

implements Wheeled{}

class

PotatoesBag {};

class Garage {

private Object keepingThing;

public Garage(Object keepingThing){ this.keepingThing = keepingThing;

}

public Object getKeepingThing(){ return keepingThing; }

}

class Man {

public static void main(String[] args) { Garage garage = new Garage (new

PotatoesBag());

Object o = garage.getKeepingThing(); PotatoesBag bag;

if (o instanceof PotatoesBag) bag = (PotatoesBag) o;

}

}

Обобщения (generics)

-позволяют указать «условный тип», с которым работает код;

-используются, когда один и тот же код применим к большому числу типов;

-позволяют повысить безопасность, за счет контроля типов на стадии компиляции программы, а не выполнения;

-в основном используются контейнерами. Все интерфейсы и классы коллекций сделали параметризированными.

interface Wheeled{}

class Crossover implements Wheeled{}

class Hatchback

implements Wheeled{}

class

Trailer

implements Wheeled{}

class

PotatoesBag {};

class Garage<T> {

private T keepingThing;

public Garage(T keepingThing){ this.keepingThing = keepingThing; }

public T getKeepingThing(){ return keepingThing;

}

}

class Man {

public static void main(String[] args) { Garage<Wheeled> garage = new Garage<Wheeled>

(new Crossover());

Garage<PotatoesSack> anotherGarage = new Garage<PotatoesBag> (new

PotatoesBag());

PotatoesBag bag = anotherGarage.getKeepingThing();

}

}

Обобщения (generics)

-код работает только с тем типом, который указан в угловых

скобках;

-позволяют создавать более компактный код, чем при использовании ссылок типа Object;

-обеспечивают автоматическую проверку и приведение типов;

-позволяют создавать хороший повторно используемый код.

Особенности параметризованных типов

Использовать примитивные типы в качестве параметрических типов нельзя. Если одинаковые настраиваемые типы имеют различные аргументы (типы-параметры), то это различные типы.

//несовместимые,различныетипы

Garage<Wheeled> garage; Garage<Crossover> anotherGarage;

Статические компоненты класса не могут использовать его типыпараметры. Также настраиваемый класс не может расширять класс Throwable.

Стирание типа

В обобщенном коде информация о параметрах-типах обобщения стирается (это значит, что при использовании обобщения любая конкретная информация о типе теряется). Тип известен только на стадии компиляции (во время статической проверки типов). После этого каждый обобщенный тип стирается, то есть заменяется необобщенным верхним ограничением. Компилятор обеспечивает внутреннюю целостность использования типов, контролируя их на «входе» и «выходе», самостоятельно выполняя приведения типов.

Миграционная совместимость

Обобщения не были частью языка с самого начала, и появились только в версии 1.5. Стирание необходимо, чтобы можно было использовать обобщенный клиентский код с необобщенными библиотеками и наоборот.

Расплата за стирание

Операции, для выполнения которых нужно точно знать типы времени выполнения, работать не будут.

-

Приведение типов:

(T) var;

-

Операция instanceof:

varue instaceof T;

-

Операция new

T

var = new T();