Transcript
75-62 Técnicas de Programación Concurrentes II Lic. Ing. Osvaldo Clúa 2008
Facultad de Ingeniería Universidad de Buenos Aires
Java Generics
Programación Genérica ●
Los programas se escriben en función de tipos que se especificarán mas tarde.
FIUBA 2008
–
Permite escribir algoritmos mas generales.
–
Existen en Ada, Eiffel, Java, C#, Visual Basic .NET y Haskell.
–
En C++ hay una facilidad parecida en precompilación conocida como Templates
75-08 Sistemas Operativos Prof. Lic. Ing. Osvaldo Clúa
2
Generics en Java ●
●
Java puede tener Clases, tipos y Métodos Genéricos. –
Proveen una forma de chequear tipos en compilación.
–
Manteniendo los programas legibles y expresivos.
También se conoce esta propiedad como Polimorfismo Paramétrico o de Tipos.
FIUBA 2008
75-08 Sistemas Operativos Prof. Lic. Ing. Osvaldo Clúa
3
Motivación ●
Se quiere imprimir un arreglo sin conocer el tipo de sus elementos. public static void printAr(E a[]){ int i=0; for (E elem:a) System.out.println((i++)+")="+elem); } public static void main(String[] args) { Integer ia[]={10,20,30,40}; Double da[]={7.5,3.4,5.6}; String sa[]={"En","un","overo","rosao"}; printAr(ia); printAr(da); printAr(sa); } }
FIUBA 2008
75-08 Sistemas Operativos Prof. Lic. Ing. Osvaldo Clúa
4
Ejercicios ●
¿Cómo infiere el tipo del parámetro de printAr(...) en los llamados? –
●
¿Puede llamarse especificando el tipo: Gene01.printAr (...) ?
Resolver este mismo ejemplo usando: –
Polimorfismo.
–
Sobrecarga de métodos.
FIUBA 2008
75-08 Sistemas Operativos Prof. Lic. Ing. Osvaldo Clúa
5
Un Ejemplo ●
Se desarrollará una pila y una lista usando Generics. –
El layout del código se optimizó para que cupiera en las slides. ●
●
Se quitaron líneas en blanco y comentarios javadoc que son obligatorios en las entregas.
La pila y la lista funcionan sobre dos clases base ejemplo: Fracción y java.lang.Integer
FIUBA 2008
75-08 Sistemas Operativos Prof. Lic. Ing. Osvaldo Clúa
6
La clase base Fracción (1) public class Fraccion { private int num; private int den; public Fraccion(){num=1; den=1;} public Fraccion(Fraccion f){num=f.num; den=f.den;} public Fraccion(int n,int d) { setNum(n); setDen(d); normalizar(); } public int getNum() { return num; } public void setNum(int num) { this.num = num; normalizar(); } public int getDen() { return den; }
FIUBA 2008
75-08 Sistemas Operativos Prof. Lic. Ing. Osvaldo Clúa
7
La clase base Fracción (2) public void setDen(int den) { this.den = den; normalizar(); } private void normalizar(){ int mcd=Math.abs(mcd(num,den)); num=num/mcd; den=den/mcd; } static private int mcd(int x,int y){ if (y==0)return x; else return mcd(y, x%y); } public String toString(){ return num+"/"+den; } } FIUBA 2008
75-08 Sistemas Operativos Prof. Lic. Ing. Osvaldo Clúa
8
La Pila Genérica import Fraccion.Fraccion; public class PilaGen { class NodoGe { E dato; NodoGe sig; NodoGe(E o, NodoGe s) { dato = o; sig = s; } } NodoGe top; public PilaGen() {
top = null; }
public void push(E o) { top = new NodoGe(o, top); } public E pop() { E x = top.dato; top = top.sig; return x; } public boolean isEmpty() { return top == null;}
FIUBA 2008
75-08 Sistemas Operativos Prof. Lic. Ing. Osvaldo Clúa
9
Prueba de la Pila Genérica i public static void main(String[] args) { PilaGen pila = new PilaGen(); PilaGen pila1 = new PilaGen(); // error al tratar de infiltrar un Integer, detectado en compilacion // pila.push (new Integer(3)); pila.push(new Fraccion(7, 3)); pila.push(new Fraccion(4, 5)); pila.push(new Fraccion(3, 4)); //saca de pila y pone en pila1 while (!pila.isEmpty()) { Fraccion o = pila.pop(); System.out.println("retirado " + o); pila1.push(o); } //saca de pila1 y accede al denominador while (!pila1.isEmpty()) { System.out.println("Denominador " + (pila1.pop()).getDen()); } } } FIUBA 2008
75-08 Sistemas Operativos Prof. Lic. Ing. Osvaldo Clúa
10
Ejercicios ●
Hacer un programa similar usando polimorfismo. –
Todos son descendientes de Object.
–
¿Qué pasa con el error al “infiltrar” un Integer?
FIUBA 2008
75-08 Sistemas Operativos Prof. Lic. Ing. Osvaldo Clúa
11
La Lista Genérica ●
FIUBA 2008
Es un código parecido con los métodos de la figura. –
También usa una clase interna Nodo.
–
Los métodos privados se usan para recursividad.
75-08 Sistemas Operativos Prof. Lic. Ing. Osvaldo Clúa
12
Un Sort genérico public class Utiles{ static void sortSel (ListaGen l, Comparator c) { for (int i=0;i<=l.size();i++){ E uno=l.datAt(i); for (int j=i+1;j0){ l.ponerEn(j,uno); l.ponerEn(i,dos); uno=l.datAt(i); } } } } }
FIUBA 2008
Es un sort por selección en una class de utilitarios. ●
Recibe una ListaGen y un comparador. ●
75-08 Sistemas Operativos Prof. Lic. Ing. Osvaldo Clúa
● ●
Que devuelve (-1,0,1) Como el pedido por la interface java.util.Comparator
13
Prueba de la Lista Genérica import Integer.IntCmp; import Fraccion.FracCmp; import Fraccion.Fraccion; public class PruLG { public static void main(String[] args) { ListaGen li = new ListaGen(); li.agregar(13); li.agregar(54); li.agregar(2); li.agregar(23); li.print(); Utiles.sortSel(li, new IntCmp()); li.print();
FIUBA 2008
ListaGen lf = new ListaGen(); lf.agregar(new Fraccion(2, 4)); lf.agregar(new Fraccion(1, 3)); lf.agregar(new Fraccion(1, 16)); lf.agregar(new Fraccion(5, 8)); lf.agregar(new Fraccion(7, 17)); lf.print(); Utiles.sortSel(lf, new FracCmp()); lf.print(); } }
Los Comparator está en clases apartes (FracCmp e IntCmp)
75-08 Sistemas Operativos Prof. Lic. Ing. Osvaldo Clúa
14
Usando Clases anónimas ●
Para las llamadas al sort podría usarse Utiles.sortSel(li, new Comparator() { public int compare(Integer o1, Integer o2) { return o1 – o2; } }); Utiles.sortSel(lf, new Comparator() { public int compare(Fraccion o1, Fraccion o2) { return (int) Math.signum(((double) o1.getNum() / (double) (o1.getDen())) ((double) o2.getNum() / (double) (o2.getDen()))); } });
FIUBA 2008
75-08 Sistemas Operativos Prof. Lic. Ing. Osvaldo Clúa
15
Wildcard type (?) ●
Se usa para imponer alguna restricción en los tipos usados como argumentos. –
significa que admite cualquier tipo que extienda a la clase Base.
–
significa que admite cualquier tipo que sea supertipo de la clase Base.
–
significa que admite cualquier tipo (sin nombrarlo).
FIUBA 2008
75-08 Sistemas Operativos Prof. Lic. Ing. Osvaldo Clúa
16
Type erasure ●
●
En compilación se verifican los tipos de los parámetros y argumentos Generics. –
Después se pierde toda información sobre el tipo.
–
Este procedimiento se llama type erasure.
Hay una sola copia del código de la estructura genérica, compartido por todas sus instancias
FIUBA 2008
75-08 Sistemas Operativos Prof. Lic. Ing. Osvaldo Clúa
17
¿Cuál es el tipo? public static void main(String[] args) { ListaGen li = new ListaGen(); ListaGen lf = new ListaGen(); if (li.getClass() == lf.getClass()) { System.out.println("Iguales"); } else { System.out.println("Distintas"); } System.out.println("El tipo de lf es: "+lf.getClass().getName()); } ●
Li y lf son listas de distintos tipos. –
●
Esta información se pierde en ejecución.
Las estructuras genéricas no pueden ser static.
FIUBA 2008
75-08 Sistemas Operativos Prof. Lic. Ing. Osvaldo Clúa
18