genéricos en Java facilitan parametric polymorphism. Por medio de parámetros de tipo, puede pasar argumentos a tipos. Así como un método como String foo(String s)
modela cierto comportamiento, no solo para una cadena en particular, sino para cualquier cadena s
, un tipo como List<T>
modela cierto comportamiento, no solo para un tipo específico, sino para cualquier tipo. List<T>
dice que para cualquier tipo T
, existe un List
de T
s. Entonces List
es en realidad un tipo constructor. Toma un tipo como argumento y construye otro tipo como resultado.
Aquí hay un par de ejemplos de tipos genéricos que uso todos los días. En primer lugar, una interfaz genérica de gran utilidad:
public interface F<A, B> {
public B f(A a);
}
Esta interfaz dice que para cualquier par de tipos, A
y B
, hay una función (llamada f
) que toma un A
y devuelve un B
. Al implementar esta interfaz, A
y B
pueden ser de cualquier tipo que desee, siempre y cuando proporcione una función f
que tome la primera y devuelva la última. He aquí un ejemplo de implementación de la interfaz:
F<Integer, String> intToString = new F<Integer, String>() {
public String f(int i) {
return String.valueOf(i);
}
}
Antes de genéricos, el polimorfismo se logró mediante la subclasificación usando la palabra clave extends
. Con los genéricos, en realidad podemos eliminar la subclasificación y usar polimorfismo paramétrico. Por ejemplo, considere una clase parametrizada (genérica) utilizada para calcular códigos hash para cualquier tipo. En lugar de anular Object.hashCode(), usaríamos una clase genérica de esta manera:
public final class Hash<A> {
private final F<A, Integer> hashFunction;
public Hash(final F<A, Integer> f) {
this.hashFunction = f;
}
public int hash(A a) {
return hashFunction.f(a);
}
}
Esto es mucho más flexible que el uso de la herencia, porque podemos permanecer con el tema de la utilización de la composición y el polimorfismo paramétrico sin bloquear abajo jerarquías frágiles.
Los genéricos de Java no son perfectos. Puede abstraer sobre tipos, pero no puede abstraer sobre constructores de tipo, por ejemplo. Es decir, puede decir "para cualquier tipo T", pero no puede decir "para ningún tipo T que tenga un parámetro de tipo A".
I wrote an article about these limits of Java generics, here.
The source for a lot of useful generic types can be found here.. Consulte también la fuente de la biblioteca Java estándar, si aún no lo hizo.
Cualquier cosa de bajo nivel que realmente desee implementar con matrices es probablemente un mal ejemplo. –