SCJP 6
     Clase 7 – Generics




    Ezequiel Aranda
Sun Microsystems Campus
      Ambassador
Disclaimer & Acknowledgments
>!Even though Ezequiel Aranda is a full-time employee of Sun
  Microsystems, the contents here are created as his own
  personal endeavor and thus does not reflect any official
  stance of Sun Microsystems.
>!Sun Microsystems is not responsible for any inaccuracies in
  the contents.
>!Acknowledgments – The slides of this presentation are made
  from “SCJP Unit 7” by Warit Wanwithu and Thanisa
  Kruawaisayawan and SCJP Workshop by P. Srikanth.
>!This slides are Licensed under a Creative Commons
  Attribution – Noncommercial – Share Alike 3.0
   >!http://creativecommons.org/licenses/by-nc-sa/3.0/
AGENDA

>! enerics
 G
>! étodos con generics
 M
>! eclaraciones con generics
 D
Generics

>! a manera antigua:
 L
  List myList = new ArrayList();
  myList.add("Fred");
  myList.add(new Dog());
  myList.add(new Integer(42));
>! os métodos que obtenian los objetos de las
 L
 colecciones sólo podían tener un único tipo
 de retorno: java.lang.Object
   String s = (String) myList.get(0);
La manera nueva: Generics

  List<String> myList = new
   ArrayList<String>();
  myList.add("Fred");
  myList.add(new Dog()); // error
>! stamos diciéndole al compilador que esta
 E
 colección solo puede contener Strings.
  String s = myList.get(0);
La manera nueva: Generics (II)

>! l tipo de los retornos puede ser declarado
 E
 como un generic también:
  public Set<Dog> getDogList() {
      Set<Dog> dogs = new
      HashSet<Dog>();
      // más código para insertar perros
      return dogs;
  }
Mezclando generics con non-
           generics
List<Integer> myList = new
 ArrayList<Integer>();
myList.add(4);
myList.add(6);
Adder adder = new Adder();
int total = adder.addAll(myList);
System.out.println(total);
class Adder {
    int addAll(List list) {
        Iterator it = list.iterator();
        int total = 0;
     while (it.hasNext()) {
          int i =
        ((Integer)it.next()).intValue();
         total += i;
     }
     return total;
    }
}
List<Integer> myList = new
  ArrayList<Integer>();
myList.add(4);
myList.add(6);
Inserter in = new Inserter();
in.insert(myList);
class Inserter {
    void insert(List list) {
        list.add(new String("42"));
    }
}
Mezclando generics con non-
             generics
>! todo eso, ¿Funciona?
 Y
>! amentablemente, si (compila y corre).
 L
>! e hecho, el compilador nos advertirá (a
 D
 través de un warning) de que estamos
 corriendo un riesgo importante al enviar
 nuestra lista genérica a un método que no lo
 es.
>! in embargo, un warning no es más que una
 S
 advertencia. Es decir, no se lo considera un
 error.
Polimorfismo y generics

>! udimos asignar un ArrayList a una referencia
 P
 a List porque List es un supertipo de ArrayList.
  List<Integer> myList = new
   ArrayList<Integer>();
>! ero, ¿Podemos hacer esto?
 P
  class Parent { }
  class Child extends Parent { }
  List<Parent> myList = new
   ArrayList<Child>();
Polimorfismo y Generics (II)

>! n la declaración la regla es muy simple, el
 E
 tipo declarado en lado izquierdo debe ser el
 mismo que el tipo en el lado derecho.
  List<JButton> myList = new
   ArrayList<JButton>();
  List<Object> myList = new
   ArrayList<Object>();
  List<Integer> myList =
   newArrayList<Integer>();
Métodos con Generics
public static void checkAnimals
  (ArrayList<Animal> animals) {
    for(Animal a : animals) {
     a.checkup();}}
public static void main(String[] args) {
    List<Dog> dogs = new ArrayList<Dog>();
    List<Cat> cats = new ArrayList<Cat>();
    List<Bird> birds = new ArrayList<Bird>();
    checkAnimals(dogs); // List<Dog>
    checkAnimals(cats); // List<Cat>
    checkAnimals(birds); // List<Bird>
}
Métodos con Generics (II)

>! o pueden asignarse ArrayLists de subtipos
 N
 de Animal al ArrayList del supertipo Animal.
>! l compilador detendrá la compilación.
 E
>! a única cosa que puede pasarse como
 L
 parámetro en un método cuyo argumento sea
 un ArrayList<Animal> será un
 ArrayList<Animal>
Métodos con Generics (III)

  public void addAnimal
   (ArrayList<Animal> animals) {
      animals.add(new Dog());
      //a veces, vale...
  }
>! odríamos, sin embargo, hacer algo como lo
 P
 que se ve arriba, lo cual compilará siempre y
 cuando lo que pasemos al método sea un
 ArrayList<Animal>.
Métodos con Generics (IV)

>! ay un mecanismo para “decirle” al
 H
 compilador que podemos aceptar cualquier
 subtipo del argumento declarado en la
 parametrización, porque no vamos a agregar
 nada en la colección.
>! icho mecanismo se llama “Wildcard”.
 D
  public void addAnimal(List<?
   extends Animal> animals)
Métodos con Generics (V)

>! on <? extends Animal> estamos diciendo
 C
 “aquí podemos asignar una colección que sea
 un subtipo de List y/o este parametrizada con
 un subtipo de Animal…”
>! … Y prometemos no agregar nada a la
 “
 colección dentro de este método”.
  public void addAnimal(List<?
   extends Animal> animals) {
    animals.add(new Dog());
  // ¡NO! no podemos agregar nada
Métodos con Generics (VI)
>!Hay una forma de usar un wildcard y
  que nos sea permitido agregar
  elementos a la colección: la palabra
  “super”.
  public static void addAnimal(List<? super
    Dog> animals)
>!Esencialmente, estamos diciendo “Don compilador,
  acepte cualquier lista parametrizada con Dog o un
  supertipo de Dog. Cualquier cosa más abajo en el
  árbol de herencia, no; pero cualquier cosa más
  arriba, sí”.
Métodos con Generics (VII)
public static void addAnimal(List<? super
  Dog> animals) {
animals.add(new Dog());
}
public static void main(String[] args) {
List<Animal> animals = new
  ArrayList<Animal>();
animals.add(new Dog());
addAnimal(animals);
}
Pregunta

>!public void foo(List<?> list) { }
>!public void foo(List<Object> list)
  { }
>! En que se diferencian?
 ¿
Métodos con Generics (VIII)

  public void foo(List<?> list) { }
>! implemente significa “cualquier tipo”.
 S
>! ualquier List podría asignarse al argumento.
 C
>! in usar “super”, no podremos agregar nada
 S
 a list.
Métodos con Generics (IX)

  public void foo(List<Object> list)
   {}
>! ignifica que el método solo puede tomar una
 S
 List<Object>, no una lista parametrizada en
 algún subtipo de Object.
>! in embargo, podremos agregar cosas a la
 S
 colección.
Pregunta
1)! List<?> list = new ArrayList<Dog>();
2)! List<? extends Animal> aList = new
    ArrayList<Dog>();
3)! List<?> foo = new ArrayList<? extends
    Animal>();
4)! List<? extends Dog> cList = new
    ArrayList<Integer>();
5)! List<? super Dog> bList = new
    ArrayList<Animal>();
6)! List<? super Animal> dList = new
    ArrayList<Dog>();

>! ¿Cuales compilan?
Declaraciones con Generics

  public class Bucket<E>{ boolean
   add(E o) }

>! <E>” es una marcador de
 “
 sustitución para el tipo que
 utilicemos. La interfaz List
 funciona en este caso como
 un template que, cuando
 escribamos nuestro código,
 cambiaremos por el tipo
 deseado.
Declaraciones con Generics (II)
>! n otras palabras, el tipo que utilicemos para
 E
 reemplazar ‘E’ cuando declaremos nuestras
 instancias será lo que podamos agregar a las
 colecciones involucradas.
  Bucket<Animal> list = new
   Bucket<Animal>();
>! a ‘E’ pasa a ser un marcador de “coloque el
 L
 tipo deseado aquí” a ser específicamente el
 tipo “Animal”, y el método add a comportarse
 de la siguiente forma:
  boolean add(Animal a)
import java.util.*;
public class RentalGeneric<T> {
    private List<T> rentalPool;
    private int maxNum;
    public RentalGeneric( int maxNum, List<T>
    rentalPool) {
        this.maxNum = maxNum;
        this.rentalPool = rentalPool;
    }
    public T getRental() {
     return rentalPool.get(0);
    }
    public void returnRental(T returnedThing) {
        rentalPool.add(returnedThing);
    }
}
public class AnimalHolder<T extends
  Animal>{
    T animal;
    public static void main(String[]
    args) {
     AnimalHolder<Dog> dogHolder =
    new AnimalHolder<Dog>(); // OK
     AnimalHolder<Integer> x = new
    AnimalHolder<Integer>(); // KO
    }
}
Creando Métodos parametrizados
import java.util.*;
public class CreateAnArrayList {
    public <T> void makeArrayList(T t) {
        /* Tomamos un objeto de un tipo
        desconocido y usamos ‘T’ para representar
        dicho tipo.*/
     List<T> list = new ArrayList<T>();
        // Ahora podemos crear la lista usando ‘T’
        list.add(t);
    }
}
Preguntas

Clase7 generics

  • 1.
    SCJP 6 Clase 7 – Generics Ezequiel Aranda Sun Microsystems Campus Ambassador
  • 2.
    Disclaimer & Acknowledgments >!Eventhough Ezequiel Aranda is a full-time employee of Sun Microsystems, the contents here are created as his own personal endeavor and thus does not reflect any official stance of Sun Microsystems. >!Sun Microsystems is not responsible for any inaccuracies in the contents. >!Acknowledgments – The slides of this presentation are made from “SCJP Unit 7” by Warit Wanwithu and Thanisa Kruawaisayawan and SCJP Workshop by P. Srikanth. >!This slides are Licensed under a Creative Commons Attribution – Noncommercial – Share Alike 3.0 >!http://creativecommons.org/licenses/by-nc-sa/3.0/
  • 3.
    AGENDA >! enerics G >!étodos con generics M >! eclaraciones con generics D
  • 4.
    Generics >! a maneraantigua: L List myList = new ArrayList(); myList.add("Fred"); myList.add(new Dog()); myList.add(new Integer(42)); >! os métodos que obtenian los objetos de las L colecciones sólo podían tener un único tipo de retorno: java.lang.Object String s = (String) myList.get(0);
  • 5.
    La manera nueva:Generics List<String> myList = new ArrayList<String>(); myList.add("Fred"); myList.add(new Dog()); // error >! stamos diciéndole al compilador que esta E colección solo puede contener Strings. String s = myList.get(0);
  • 6.
    La manera nueva:Generics (II) >! l tipo de los retornos puede ser declarado E como un generic también: public Set<Dog> getDogList() { Set<Dog> dogs = new HashSet<Dog>(); // más código para insertar perros return dogs; }
  • 7.
    Mezclando generics connon- generics List<Integer> myList = new ArrayList<Integer>(); myList.add(4); myList.add(6); Adder adder = new Adder(); int total = adder.addAll(myList); System.out.println(total);
  • 8.
    class Adder { int addAll(List list) { Iterator it = list.iterator(); int total = 0; while (it.hasNext()) { int i = ((Integer)it.next()).intValue(); total += i; } return total; } }
  • 9.
    List<Integer> myList =new ArrayList<Integer>(); myList.add(4); myList.add(6); Inserter in = new Inserter(); in.insert(myList); class Inserter { void insert(List list) { list.add(new String("42")); } }
  • 10.
    Mezclando generics connon- generics >! todo eso, ¿Funciona? Y >! amentablemente, si (compila y corre). L >! e hecho, el compilador nos advertirá (a D través de un warning) de que estamos corriendo un riesgo importante al enviar nuestra lista genérica a un método que no lo es. >! in embargo, un warning no es más que una S advertencia. Es decir, no se lo considera un error.
  • 11.
    Polimorfismo y generics >!udimos asignar un ArrayList a una referencia P a List porque List es un supertipo de ArrayList. List<Integer> myList = new ArrayList<Integer>(); >! ero, ¿Podemos hacer esto? P class Parent { } class Child extends Parent { } List<Parent> myList = new ArrayList<Child>();
  • 12.
    Polimorfismo y Generics(II) >! n la declaración la regla es muy simple, el E tipo declarado en lado izquierdo debe ser el mismo que el tipo en el lado derecho. List<JButton> myList = new ArrayList<JButton>(); List<Object> myList = new ArrayList<Object>(); List<Integer> myList = newArrayList<Integer>();
  • 13.
    Métodos con Generics publicstatic void checkAnimals (ArrayList<Animal> animals) { for(Animal a : animals) { a.checkup();}} public static void main(String[] args) { List<Dog> dogs = new ArrayList<Dog>(); List<Cat> cats = new ArrayList<Cat>(); List<Bird> birds = new ArrayList<Bird>(); checkAnimals(dogs); // List<Dog> checkAnimals(cats); // List<Cat> checkAnimals(birds); // List<Bird> }
  • 14.
    Métodos con Generics(II) >! o pueden asignarse ArrayLists de subtipos N de Animal al ArrayList del supertipo Animal. >! l compilador detendrá la compilación. E >! a única cosa que puede pasarse como L parámetro en un método cuyo argumento sea un ArrayList<Animal> será un ArrayList<Animal>
  • 15.
    Métodos con Generics(III) public void addAnimal (ArrayList<Animal> animals) { animals.add(new Dog()); //a veces, vale... } >! odríamos, sin embargo, hacer algo como lo P que se ve arriba, lo cual compilará siempre y cuando lo que pasemos al método sea un ArrayList<Animal>.
  • 16.
    Métodos con Generics(IV) >! ay un mecanismo para “decirle” al H compilador que podemos aceptar cualquier subtipo del argumento declarado en la parametrización, porque no vamos a agregar nada en la colección. >! icho mecanismo se llama “Wildcard”. D public void addAnimal(List<? extends Animal> animals)
  • 17.
    Métodos con Generics(V) >! on <? extends Animal> estamos diciendo C “aquí podemos asignar una colección que sea un subtipo de List y/o este parametrizada con un subtipo de Animal…” >! … Y prometemos no agregar nada a la “ colección dentro de este método”. public void addAnimal(List<? extends Animal> animals) { animals.add(new Dog()); // ¡NO! no podemos agregar nada
  • 18.
    Métodos con Generics(VI) >!Hay una forma de usar un wildcard y que nos sea permitido agregar elementos a la colección: la palabra “super”. public static void addAnimal(List<? super Dog> animals) >!Esencialmente, estamos diciendo “Don compilador, acepte cualquier lista parametrizada con Dog o un supertipo de Dog. Cualquier cosa más abajo en el árbol de herencia, no; pero cualquier cosa más arriba, sí”.
  • 19.
    Métodos con Generics(VII) public static void addAnimal(List<? super Dog> animals) { animals.add(new Dog()); } public static void main(String[] args) { List<Animal> animals = new ArrayList<Animal>(); animals.add(new Dog()); addAnimal(animals); }
  • 20.
    Pregunta >!public void foo(List<?>list) { } >!public void foo(List<Object> list) { } >! En que se diferencian? ¿
  • 21.
    Métodos con Generics(VIII) public void foo(List<?> list) { } >! implemente significa “cualquier tipo”. S >! ualquier List podría asignarse al argumento. C >! in usar “super”, no podremos agregar nada S a list.
  • 22.
    Métodos con Generics(IX) public void foo(List<Object> list) {} >! ignifica que el método solo puede tomar una S List<Object>, no una lista parametrizada en algún subtipo de Object. >! in embargo, podremos agregar cosas a la S colección.
  • 23.
    Pregunta 1)! List<?> list= new ArrayList<Dog>(); 2)! List<? extends Animal> aList = new ArrayList<Dog>(); 3)! List<?> foo = new ArrayList<? extends Animal>(); 4)! List<? extends Dog> cList = new ArrayList<Integer>(); 5)! List<? super Dog> bList = new ArrayList<Animal>(); 6)! List<? super Animal> dList = new ArrayList<Dog>(); >! ¿Cuales compilan?
  • 24.
    Declaraciones con Generics public class Bucket<E>{ boolean add(E o) } >! <E>” es una marcador de “ sustitución para el tipo que utilicemos. La interfaz List funciona en este caso como un template que, cuando escribamos nuestro código, cambiaremos por el tipo deseado.
  • 25.
    Declaraciones con Generics(II) >! n otras palabras, el tipo que utilicemos para E reemplazar ‘E’ cuando declaremos nuestras instancias será lo que podamos agregar a las colecciones involucradas. Bucket<Animal> list = new Bucket<Animal>(); >! a ‘E’ pasa a ser un marcador de “coloque el L tipo deseado aquí” a ser específicamente el tipo “Animal”, y el método add a comportarse de la siguiente forma: boolean add(Animal a)
  • 26.
    import java.util.*; public classRentalGeneric<T> { private List<T> rentalPool; private int maxNum; public RentalGeneric( int maxNum, List<T> rentalPool) { this.maxNum = maxNum; this.rentalPool = rentalPool; } public T getRental() { return rentalPool.get(0); } public void returnRental(T returnedThing) { rentalPool.add(returnedThing); } }
  • 27.
    public class AnimalHolder<Textends Animal>{ T animal; public static void main(String[] args) { AnimalHolder<Dog> dogHolder = new AnimalHolder<Dog>(); // OK AnimalHolder<Integer> x = new AnimalHolder<Integer>(); // KO } }
  • 28.
    Creando Métodos parametrizados importjava.util.*; public class CreateAnArrayList { public <T> void makeArrayList(T t) { /* Tomamos un objeto de un tipo desconocido y usamos ‘T’ para representar dicho tipo.*/ List<T> list = new ArrayList<T>(); // Ahora podemos crear la lista usando ‘T’ list.add(t); } }
  • 29.