Вы находитесь на странице: 1из 10

Genricos

Los Genricos aaden estabilidad a su cdigo, haciendo que ms errores sean detectables en
tiempo de compilacin.

Por qu utilizar los genricos?


En pocas palabras, los genricos permiten tipos (clases e interfaces) para ser parmetros en la
definicin de clases, interfaces y mtodos. Los parmetros de tipo proporcionan una forma para que
usted pueda volver a usar el mismo cdigo con diferentes entradas.
El cdigo que utiliza los genricos tiene muchas ventajas sobre el cdigo no genrico:

Controles

ms

fuertes

de

tipo

en

tiempo

de

compilacin.

Compilador Java aplica fuerte tipo de chequeo a cdigos genricos y asuntos de errores de
cdigo por si el cdigo viola algn tipo de seguridad. La fijacin de los errores en tiempo de
compilacin es ms fcil que la fijacin de los errores de ejecucin, que puede ser difcil de
encontrar.

. Eliminacin de los casteos

Habilitacin

de

los

programadores

para

implementar

algoritmos

genricos.

Mediante el uso de los genricos, los programadores pueden implementar algoritmos


genricos que trabajan en las colecciones de diferentes tipos, puede ser personalizado, y
son de tipo seguro y fcil de leer.

Tipos genricos
Un tipo genrico es una clase genrica o interfaz que est parametrizado con tipos.
Una clase genrica se define con el siguiente formato:

nombre de la clase <T1, T2, ..., Tn> {/ * ... * /}


Una clase sin utilizar genricos seria:
public class Box {
private Object object;
public void set(Object object) { this.object = object; }
public Object get() { return object; }
}

Reescribindolo la clase anterior utilizando genricos quedara de la siguiente manera:


public class Box<T> {
// T stands for "Type"
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}

La seccin tipo de parmetro est delimitado por parntesis angulares (<>), seguido del nombre
de la clase. Se especifica los parmetros de tipo (tambin llamadas variables de tipo)
T1, T2, ..., y Tn.

como

Por convencin, los nombres de los parmetros de tipo son letras individuales, en maysculas. Sin
esta convencin, sera difcil decir la diferencia entre una variable de tipo y una clase o interfaz
nombre comn.
Los nombres de los parmetros tipo ms comnmente utilizados son:

E - Element (used extensively by the Java Collections Framework)

K - Key

N - Number

T - Type

V - Value

S,U,V etc. - 2nd, 3rd, 4th types

Invocando y Instanciar un tipo genrico


Para hacer referencia a una clase genrica Box desde de su cdigo, debe realizar una invocacin
de tipo genrico, que sustituye a T con algn valor concreto, como Entero:

Box <Integer> integerBox = new Box <Integer> ();

El diamante
En Java SE 7 y versiones posteriores, puede reemplazar los argumentos de tipo necesarios para
invocar el constructor de una clase genrica con un conjunto vaco de argumentos de tipo (<>)
siempre que el compilador pueda determinar o inferir, los argumentos de tipo del contexto. Este par
de parntesis angulares, <>, es informalmente llamado el diamante. Por ejemplo, puede crear una
instancia de Box <Integer> con la siguiente declaracin:

Box <Integer> integerBox = new Box <> ();

Mtodos genricos
Mtodos genricos son mtodos que introducen sus propios parmetros de tipo. Esto es similar a lo
que se declara un tipo genrico, pero el alcance del parmetro de tipo se limita al mtodo en el que
se declara.
La sintaxis de un mtodo genrico incluye un parmetro de tipo, dentro de parntesis angulares, y
se presenta antes del tipo de retorno del mtodo.
La clase Util incluye un mtodo genrico, comparare, que compara un par de objetos:

public class Util {


public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
return p1.getKey().equals(p2.getKey()) &&
p1.getValue().equals(p2.getValue());
}
}

Parmetros de Tipo Acotados


Puede haber momentos en los que desea restringir los tipos que se pueden utilizar como
argumentos de tipo en un tipo parametrizado. Por ejemplo, un mtodo que funciona con nmeros
solamente podra querer aceptar casos de Nmero o de sus subclases. Los parmetros de tipo
acotados son para eso.
Para declarar un parmetro de tipo acotado, escriba el nombre del parmetro de tipo, seguido por la
palabra clave extends, seguido de su limite superior, que en este ejemplo es Number.
public class Box<T> {
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
public <U extends Number> void inspect(U u){
System.out.println("T: " + t.getClass().getName());
System.out.println("U: " + u.getClass().getName());
}
public static void main(String[] args) {
Box<Integer> integerBox = new Box<Integer>();
integerBox.set(new Integer(10));
integerBox.inspect("some text"); // error: this is still String!
}
}

La instruccin integerBox.inspect("some text"); dara error en tiempo de compilacin porque


el argumento recibido es un String el cual no es un subtipo de Number.

Genricos, Herencia y subtipos


Es posible asignar un objeto de un tipo a un objeto de otro tipo, siempre que los tipos son
compatibles. Por ejemplo, puede asignar un Integer a un Object, ya que Object es un
subtipo de Integer :

Object someObject = new Object ();


Integer someInteger = new Integer (10);
someObject = someInteger; // OK
Lo mismo ocurre con los genricos. Puede realizar un tipo de invocacin genrica,
pasando Number como argumento de tipo, y cualquier invocacin subsiguiente de esta se le
permitir si el argumento es compatible con Number:
public void someMethod(Number n) { /* ... */ }
someMethod(new Integer(10));
someMethod(new Double(10.1));

// OK
// OK

Ahora consideremos el siguiente mtodo:

public void boxTest (Box <Number> n) {/ * ... * /}


Qu tipo de argumento no se acepta? Al mirar a su firma, se puede ver que acepta un solo
argumento cuyo tipo es Box<Number>. Pero qu significa eso? Se le permite pasar Box
<Integer> o Box<Double>, como se podra esperar? La respuesta es "no", porque Box
<Integer> y Box<Double> no son subtipos de Box<Number>.

Inferencia de tipos y de instancias de las clases genricas


Puede reemplazar los argumentos de tipo necesarios para invocar el constructor de una clase
genrica con un conjunto vaco de parmetros de tipo (<>) siempre que el compilador puede
deducir los argumentos de tipo a partir del contexto. Este par de parntesis angulares se
informalmente llamado el diamante.
Por ejemplo, considere la siguiente declaracin de variable:

Map <String, Lista <String >> myMap = new HashMap <String, List
<String >> ();
Puede sustituir el tipo parametrizado del constructor con un conjunto vaco de parmetros de
tipo (<>):

Map <String, Lista <String >> myMap = new HashMap <> ();

Los Comodines
En el cdigo genrico, el signo de interrogacin (?), Llamado el comodn, representa un tipo
desconocido. El comodn se puede utilizar en una variedad de situaciones: como el tipo de un
parmetro, un campo o variable local; a veces como un tipo de retorno (aunque es mejor en la
prctica de programacin ser ms especficos). El comodn nunca se usa como un argumento de

tipo para un mtodo de invocacin genrica, una creacin de la instancia clase genrica o un
supertipo.

Comodines Acotados Superiormente


Puede utilizar un comodn acotado superiormente para relajar las restricciones a una variable. Por
ejemplo,
digamos
que
usted
quiere
escribir
un
mtodo
que
funciona
en List<Integer>, List<Double>, y List<Number>; se puede lograr esto mediante el
uso de un comodn acotado superiormente.
Para declarar un comodn delimitado superiormente, utilice el carcter comodn ('?'), Seguido
por la palabra clave extends, seguido por su lmite superior.
Para escribir el mtodo que funciona en las listas de Number y los subtipos
de Number, como Integer, Double, y
el Float,
especificara List<? extends
Number>. El
trmino List<Number> es
ms
restrictivo
que la
List<? extends
Number> porque el primero coincide solamente con una lista de tipo Nmero, mientras la segunda
con una lista de tipo Nmero o cualquiera de sus subclases.

Los comodines no acotadas


Se especifica el tipo comodn ilimitada utilizando el carcter comodn (?), Por ejemplo, List <?
>. Esto se llama una lista de tipo desconocido. Hay dos escenarios donde un comodn sin lmites
tiene un enfoque til:

Si usted est escribiendo un mtodo que puede ser implementado utilizando la


funcionalidad proporcionada por la clase Object.

Cuando el cdigo es el uso de mtodos de la clase genrica que no depende del parmetro
de tipo. Por ejemplo, List.size o list.clear. De hecho, la clase <?> Se utiliza
tan a menudo, porque la mayora de los mtodos en la clase <T> no dependen de t.

Comodines acotados inferiormente


Los comodines acotados superiormente muestran que un comodn acotada superior restringe el tipo
desconocido a ser un tipo especfico o un subtipo de ese tipo y se representa usando la palabra
clave extends. De manera similar, un comodn delimitado inferiormente restringe el tipo
desconocido para ser un tipo especfico o de un supertipo de ese tipo.
Un comodn acotada inferior se expresa utilizando el carcter comodn ('?'), Siguiendo por la
palabras clave sper , seguida de su lmite inferior: <? Super A>.

Digamos que quiere escribir un mtodo que pone objetos Integer en una lista. Para maximizar la
flexibilidad, que le gustara que el mtodo funcione en List<Integer>, List<Number>
y List<Object>, cualquier cosa que puede contener valores enteros.
Para

escribir

el

mtodo

que

funciona

en

las

listas

de enteros y

de Integer, como Integer, Number y Object,

<? sper Integer>. El

trmino List<Integer> es

ms

los

supertipos

especificara List
que
List

restrictiva

<? sper Integer>, porque el primero coincide solamente con una lista de tipo Integer,
mientras que el siguiente con un lista de cualquier tipo que es un supertipo Integer.

Preguntas y Ejercicios: genricos


1-

Escriba un mtodo genrico para contar el nmero de elementos en una coleccin que
tienen una propiedad especfica (por ejemplo, nmeros enteros impares, nmeros
primos, palindromes).

public class Generico{


public static <T> int CuentaElemento(Collection<T> c,
Propiedad<T> p){
int contador=0;
for(T elem: c)
if(p.prop(elem))
contador++;
return Contador;
}
}
Donde propiedad es una interfaz generica como la siguie:
public interface Propiedad<T>{
public boolean prop(T elem);
}
2-

Compilar la siguiente clase? Si no, por qu?

public final class Algoritmo {


public static <T> T max (T x, T y) {
volver x> y? x: y;
}
}

No compilara, porque el operador > solo puede operar con tipos de


datos primitivos numricos.

3- Escriba un mtodo genrico para intercambiar las posiciones de dos elementos


diferentes en un Array.

public <T> void Intercambia(T[] v, int x, int y){


T aux=v[x];
v[x]=v[y];
v[y]=aux;

}
4- Si el compilador se borran todos los parmetros de tipo en tiempo de compilacin,
por qu debera usar los genricos?
-

Los genricos permiten implementar algoritmos genricos.

El compilador Java impone controles ms estrictos sobre tipo cdigo genrico en tiempo de
compilacin.

Los genricos son compatibles con programacin tipos como parmetros.

5- Como es convertida la siguiente clase despus del borrado de


tipo?
public class Pair<K, V> {
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey(); { return key; }
public V getValue(); { return value; }
public void setKey(K key)
{ this.key = key; }
public void setValue(V value) { this.value = value; }
private K key;
private V value;
}

Despues del borrado de tipo el cdigo queda como sigue:


public class Pair{
public Pair(Object key, Object value){
this.key=key;
this.value=value;
}
public Object getKey(); {return key;}
public Object getValue(); {return value;}

public void setKey(Object key)

{this.key=key;}

public void setValue(Object value)

{this.value=value;}

private Object key;

private Object value;


}

6-

Cmo es convertida el siguiente mtodo despus del borrado de tipo?

public static <T extends Comparable<T>>


int findFirstGreaterThan(T[] at, T elem) {
// ...
}

Despues del borrado de tipo el metodo queda como sique:

Public static int findFirstGreaterThan(Comparable[] at, Comparable


elem){
//.
}
7- Compilara el siguiente mtodo? Y si no por qu?
public static void print(List<? extends Number> list) {
for (Number n : list)
System.out.print(n + " ");
System.out.println();
}
Si compilara porque se aplica correctamente la jerarqua de subtipos.
8-

Escriba un mtodo genrico para encontrar el elemento mximo en el


rango [ini,fin) de una lista.

public static<T entends Comparable<T>> T maximo(List<? Extends T>


lista,int ini, int fin ){
T max=lista.get(ini);
for(++ini;ini<fin;fin++)
if(max.compara(lista.get(ini))<0)
max=lista.get(ini);
return max;
}
9-

Puede compilar el siguiente cdigo? Y Sino porque?

public class Singleton<T> {


public static T getInstance() {
if (instance == null)
instance = new Singleton<T>();
return instance;
}
private static T instance = null;

No compilara porque no puedes crear un parmetro de tipo T en un campo esttico

10- Considerando la siguiente clase:


class Shape { /* ... */ }
class Circle extends Shape { /* ... */ }
class Rectangle extends Shape { /* ... */ }
class Node<T> { /* ... */ }

Puede compilar el siguiente codigo? Y sino Porque?


Node<Circle> nc = new Node<>();
Node<Shape> ns = nc;

No compilara porque Circle es un subtipo de Shape pero Node<Circle> no


es un subtipo de Node<Shape>

11- Considere la siguiente clase:

class Node<T> implements Comparable<T> {


public int compareTo(T obj) { /* ... */ }
// ...
}
Puede compilar el siguiente codigo? Y sino porque?

Node<String> node = new Node<>();


Comparable<String> comp = node;

Si compilara porque como no varia el argumento de tipo al hacer


implements de Comparable<T> se mantiene la relacin de subtipos que
implica que Node<String> es un subtipo de Comparable<String> y por lo
tanto Compila.

Вам также может понравиться