Inicio > Informática > Generics en Java… Java sucks!

Generics en Java… Java sucks!


Cuando lees discusiones en foros especializados de c++ criticando los generics de Java piensas: “dichosos fanboys, siempre llenando Internet con sus mierdas”. Hasta que tienes que diseñar una clase que usa generics de Java.

La genericidad de Java se basó en un principio en que todas las clases heredaban de la clase base Object. Esto suponía graves problemas, entre los que se encontraban los cast inseguros, y otros no tan triviales como la necesaria distinción de los métodos add y addAll en la clase List, en lugar de la sobrecarga de un solo método, como sería normal.

Unos cuantos avezados programadores de Java quisieron aportar generics a Java sin perder la compatibilidad con la máquina virtual. El método consistía en utilizar un compilador propio, que sustituía los genéricos por las clases concretas, haciendo los casts necesarios en tiempo de compilación, de manera transparente al programador. Este proyecto (project pizza) fue finalmente incorporado a Java, sin dejar de ser un apaño para añadir genéricos a Java con compatibilidad hacia atrás.

Esta aproximación presenta varios problemas, entre los que destacan:

  • La información de los genéricos se borra tras la compilación. Esto implica por ejemplo que no puedes utilizar directamente el tipo genérico T para obtener su clase y compararla con otra. Es decir, no se podría hacer algo como T.class.equals(otroObjeto.class).
  • La comprobación de tipos se retrasa hasta la ejecución, lo que nos puede generar ClassCastExceptions

Otro problema grave que presenta Java para el trabajo con genéricos (o sin ellos) son los tipos numéricos. Fue un fallo de diseño gordo, propiciado en parte por la necesidad de eficiencia, el no incluir en la jerarquía de clases los tipos básicos (int, double, boolean, etc). Es penoso que no se pueda hacer un cast de Double a Integer, sin recurrir a métodos rocambolescos, como

Integer.getInteger(unDouble.toString())

Para mi desgracia, me encuentro trabajando en un proyecto desarrollado en Java, que necesita de generics. En concreto, tengo que escribir una clase que representa una matriz de distancias, cuyas distancias pueden ser enteros o dobles.


public Interface Distances<T extends Number> {
    public T get(int i, int j);
}

Para poder lidiar de forma eficaz con los genéricos he tenido representar la matriz internamente siempre como un double, y crear una clase “NumberCaster”, que construyo con la información de la clase de T y que necesariamente tiene que indicar el programador de forma doble (cuando indica el tipo de T, y cuando pasa la clase Class de T al constructor). Esta clase se encarga de realizar las transformaciones cada vez que que se invoca al método get: de double a integer o de double a double, dependiendo de T.


public class DistancesImpl<T extends Number> {
   double[][] distances;
   NumberCaster caster;
   public DistancesImpl(Class<T extends Number> TClass) {
       if(Double.class.equals(TClass)) {
            caster = new Double2DoubleCaster();
      } else if (Integer.class.equals(TClass)){
            caster = new Double2IntegerCaster();
      }
      ...
   }

   public T get(int i, int j) {
       return caster.cast(distances[i][j]);
   }
}

public interface NumberCaster<TFrom extends Number, TTo extends Number>  {
   public TTo cast(TFrom number);
} 

public class Double2IntegerCaster extends NumberCaster<Double, Integer> {
   public Integer cast(Double number) {
       return number.intValue();
   }
} 

public class Double2DoubleCaster extends NumberCaster<Double, Double> {
   public Double cast(Double number) {
       return number;
   }
}

Existen otras formas de tratar con arrays de generics en Java, como se discute en StackOverflow, pero todas dependen de pasarle la clase Class del tipo al método. ¡Qué horror!

ACTUALIZACIÓN

He publicado una nueva solución que mejora ésta, para poder utilizar como representación interna el tipo real de T.

Categorías:Informática Etiquetas: , ,
  1. Alfon
    junio 25, 2014 a las 11:59 am

    Pues a mi me parecen la pollaaaaaaaaaa

  2. diciembre 5, 2016 a las 10:50 am
  1. junio 25, 2010 a las 10:52 am

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s