Hola,
Hace tiempo que me peleo con unos comportamientos (a mi parecer) raros de Java, y a ver quien sabe darme una respuesta del porque.
La cuestión es que de vez en cuando toca hacer factorias que retornan objetos basados en una jerarquía (1 padre, N hijos, N niveles). Para hacer algo elegante y que evite tener que andar con más casts de los que una persona cuerda puede tolerar, me copié la idea del AbstractBeanFactory de Spring, que define el siguiente método
public <T> T getBean(String name, Class<T> requiredType) throws BeansException
Esto hace que el tipo que retorna el método es el mismo que el pasado como Class en el segundo parámetro.
Ahora viene la duda 1 ¿por que el compilador obliga ha hacer un cast a T en el retorno? ¿Acaso no puede ser T cualquier clase? Como nota, AbstrasctBaseObject representa la raíz de mi jerarquía de clases del modelo.
public <T> T createObject(Properties rowProperties, Class<T> targetClass) throws InstantiationException, IllegalAccessException {
AbstractBaseObject instance = (AbstractBaseObject) targetClass.newInstance();
return (T) instance;
}
Por tal de evitar eso, le intento dar una segunda vuelta y termino con esto, la diferencia es que indico que T es subcrase de AbstractBaseObject:
public <T extends AbstractBaseObject> T createObjectByPropertiesRow2(Properties rowProperties, Class<T> targetClass) throws InstantiationException, IllegalAccessException {
AbstractBaseObject instance = targetClass.newInstance();
return (T) instance;
}
En este caso, no es necesario el cast en el newInstance ya que reconoce los tipos como compatibles, pero (duda 2), me obliga igualmente a poner un cast cast en el return. ¿Acaso no son comaptibles <T extends AbstractBase> y <AbstractBaseObject>? WTF?
A ver si algún gurú me resuelvo esto :) Lo cierto es que no es un problema bloqueante, pero siempre me ha intrigado.