Los genéricos de Java: Volviendo acotada tipo genérico

Tapas Bose:

He siguiendo el trozo de código:

public <T extends ParentException> T managedException(Exception cause) {        
    if(ExceptionA.class.isInstance(cause)) {
        return ExceptionA.class.cast(cause);
    } else if(ExceptionB.class.isInstance(cause)) {
        return ExceptionB.class.cast(cause);
    } else if(ExceptionC.class.isInstance(cause)){
        return ExceptionC.class.cast(cause);
    } else {
        return new ExceptionD(cause.getMessage(), cause);
    }
}

Aquí ExceptionA, ExceptionB, ExceptionC, ExceptionDson hijos de ParentException.

Durante la compilación, tengo los errores:

incompatible types: ExceptionA cannot be converted to T
incompatible types: ExceptionB cannot be converted to T
incompatible types: ExceptionC cannot be converted to T
incompatible types: ExceptionD cannot be converted to T

Pero, si cambio el código para:

@SuppressWarnings("unchecked")
public <T extends ParentException> T managedException(Exception cause) {        
    if(ExceptionA.class.isInstance(cause)) {
        return (T) ExceptionA.class.cast(cause);
    } else if(ExceptionB.class.isInstance(cause)) {
        return (T) ExceptionB.class.cast(cause);
    } else if(ExceptionC.class.isInstance(cause)){
        return (T) ExceptionC.class.cast(cause);
    } else {
        return (T) new ExceptionD(cause.getMessage(), cause);
    }
}

Funciona sin error de compilación.

Como se mencionó en la respuesta de la rosca SO: ¿Cómo hago el retorno del método genérico? , Fundición con Tque está permitido y otro puntero se da en este hilo: Java Generics: Tipo genérico definido como único tipo de retorno . Pero mi pregunta es: ¿por qué necesito para uso cuando el encasillamiento Tes acotada y caer todos los objetos que regresan al especificados enlazados?

Veselin Davidov:

Lo que está haciendo está mal. Es por eso que recibe el error. Puede llamar a su método con el ExceptionC exceptionC=managedException(ExceptionD d)y que va a terminar con un reparto (ExceptionC) exceptionD;y la colada se enmascara el error, pero se obtiene en tiempo de ejecución.

Cambiar su método a:

public ParentException managedException(Exception cause) {        
    if(ExceptionA.class.isInstance(cause)) {
        return ExceptionA.class.cast(cause);
    } else if(ExceptionB.class.isInstance(cause)) {
        return ExceptionB.class.cast(cause);
    } else if(ExceptionC.class.isInstance(cause)){
        return ExceptionC.class.cast(cause);
    } else {
        return new ExceptionD(cause.getMessage(), cause);
    }
}

No es necesario genéricos aquí. Todas estas excepciones son también ParentExceptions por lo que juse les puede volver. Cuando se piensa en ello está tratando de realizar la devolución método de diferentes tipos. Que no se puede hacer así, porque si usted tiene una variable que se ha inicializado de este método lo que necesita saber cuál sería el resultado. Y usted sabe que el resultado será ParentException pero no se puede saber qué tipo de excepción de los padres es que.

La razón detrás de esto es que su método si escribe así no va a regresar ParentException - se está volviendo T (una subclase). Y se puede devolver un tipo diferente de subclase y no el que usted está tratando de conseguir.

En un ejemplo más simple si tenemos:

class A {}

class B extends A{  };

class C extends A{  };

public  <T extends A> T test() {        
        return (T) new B();
}   

podemos decir que es la C c=test();que realmente tratamos de molde (C) new B();que es incompatible pero hemos enmascarado y obtenemos la excepción en tiempo de ejecución

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=197246&siteId=1
Recomendado
Clasificación