Saint Petersburg, 2011 Java Lecture Generics
Quiz ArrayList lst = new ArrayList(); Collection c = lst; lst.add("one"); lst.add(two"); lst.add(three"); lst.remove(0); c.remove(0); System.out.println(lst.size()); System.out.println(c.size()); 2
Road to Generics Класс - ящик для хранения других объектов class Box { private Object object; void add(Object object) { this.object = object; } Object get() { return object; } 3
Road to Generics Класс - ящик для хранения других объектов class Box { private Object object; void add(Object object) { this.object = object; } Object get() { return object; } При использовании необходимо кастовать к нужному типу, это небезопасно Box integerBox = new Box(); integerBox.add(new Integer(10)); Integer someInteger = (Integer) integerBox.get(); 4
Road to Generics Класс - ящик для хранения других объектов class Box { private Object object; void add(Object object) { this.object = object; } Object get() { return object; } При использовании необходимо кастовать к нужному типу, это небезопасно Box integerBox = new Box(); integerBox.add(new Integer(10)); integerBox.add(10); Integer someInteger = (Integer) integerBox.get(); //Exception!!! 5
Road to Generics Можно защититься, но это неудобно: Box integerBox = new Box(); Object content = integerBox.get(); if (content instanceof Integer) { Integer someInteger = (Integer)integerBox.get(); System.out.println(someInteger + 5); } 6
Road to Generics Можно защититься, но это неудобно: Box integerBox = new Box(); Object content = integerBox.get(); if (content instanceof Integer) { Integer someInteger = (Integer)integerBox.get(); System.out.println(someInteger + 5); } 7
Road to Generics Generics: we can do it safe and clear! class Box { private T object; void add(T object) { this.object = object; } T get() { return object; } 8
Road to Generics Generics: we can do it safe and clear! class Box { private T object; void add(T object) { this.object = object; } T get() { return object; } Соответственно, использование изменится к лучшему: Box integerBox = new Box (); integerBox.add(new Integer(10)); Integer someInteger = integerBox.get(); 9
Generic classes Generics: we can do it safe and clear! class Box { private T object; void add(T object) { this.object = object; } T get() { return object; } Соответственно, использование изменится к лучшему: Box integerBox = new Box (); integerBox.add(new Integer(10)); integerBox.add(10); // Не компилируется Integer someInteger = integerBox.get(); String someInteger = integerBox.get(); // Не компилируется 10
Generic methods Также можно объявлять generic методы: class Box { private T object; void add(T object) { this.object = object; } T get() { return object; } void inspect(U u) { System.out.println("U: " + u.getClass().getName()); } 11
Generic methods Также можно объявлять generic методы: class Box { private T object; void add(T object) { this.object = object; } T get() { return object; } static void fillBoxes(U u, List > boxes) { for (Box box : boxes) { box.add(u); } Box. fillBoxes(42, new ArrayList >()); 12
Wildcards Generic types are invariant List не наследует List : Integer[] iArray = {1, 3, 2}; Object[] oArray = iArray; // OK List iList = new ArrayList (); List oList = iList; // Не компилируется 13
Wildcards Generic types are invariant List не наследует List : Integer[] iArray = {1, 3, 2}; Object[] oArray = iArray; List iList = new ArrayList (); List oList = iList; //Не компилируется Чтобы решить эту проблему, можно использовать wildcard: – любой класс – ограничение снизу: все классы, которые являются наследниками Number – ограничение сверху: все классы, являющиеся родителями класса Number 14
Возможны множествовариантов инициализации: List list1 = new ArrayList (); List list2 = new ArrayList (); List list3 = new ArrayList (); List list4 = new ArrayList (); List is a subtype of List Когда какой wildcard использовать? 15
PECS rule PECS P roducer Extends, C onsumer Super use Foo for a T producer use Foo for a T consumer dont use ? for return type 16
PECS rule PECS P roducer Extends, C onsumer Super use Foo for a T producer use Foo for a T consumer dont use ? for return type Пример Stack : void pushAll(Collection src); – src is an E producer void popAll(Collection dst); – dst is an E consume 17
PECS rule Как можно будет использовать объекты внутри метода? void pushAll(Collection src) { dst.add(1); // Не компилируется for (Number n : src) { System.out.println(n); } for (Object o : dst) { System.out.println(o); } void popAll(Collection dst) { dst.add(new Float(1.2)); for (Number n : dst) { // Не компилируется System.out.println(n); } 18
PECS rule Как можно будет использовать объекты внутри метода? void pushAll(Collection src) { dst.add(1); // Не компилируется for (Number n : src) { System.out.println(n); } void popAll(Collection dst) { dst.add(new Float(1.2)); for (Number n : dst) { // Не компилируется System.out.println(n); } for (Object o : dst) { System.out.println(o); } 19
Wildcards in use Что можно буедт пердавать в метод? void pushAll(Collection src); void popAll(Collection dst); pushAll(new ArrayList ()); popAll(new ArrayList ()); 20
Wildcards in use Что можно буедт пердавать в метод? void pushAll(Collection src); void popAll(Collection dst); pushAll(new ArrayList ()); pushAll(new ArrayList ()); // Не компилируется popAll(new ArrayList ()); // Не компилируется popAll(new ArrayList ()); 21
References