De acuerdo con Java Language Sepecification , 3ra edición:
Deseo entender por qué se ha tomado esta decisión. ¿Qué hay de malo con las excepciones genéricas?
(Hasta donde yo sé, los genéricos son simplemente azúcar sintáctica en tiempo de compilación, y se traducirán de Object
todos modos en los .class
archivos, por lo que declarar efectivamente una clase genérica es como si todo en ella fuera un Object
. Corríjame si me equivoco .)
java
generics
exception
language-design
Hosam Aly
fuente
fuente
myList.get(i)
, obviamenteget
todavía devuelve unObject
. ¿El compilador inserta una conversiónA
para capturar parte de la restricción en tiempo de ejecución? Si no, el OP tiene razón en que al final se reduce aObject
s en tiempo de ejecución. (El archivo de clase ciertamente contiene metadatos sobreA
, pero solo son metadatos AFAIK.)Respuestas:
Como dijo Mark, los tipos no son reificables, lo cual es un problema en el siguiente caso:
Ambos
SomeException<Integer>
ySomeException<String>
se borran al mismo tipo, no hay forma de que la JVM distinga las instancias de excepción y, por lo tanto, no hay forma de saber quécatch
bloque debe ejecutarse.fuente
Aquí hay un ejemplo simple de cómo usar la excepción:
El cuerpo de la instrucción TRy arroja la excepción con un valor dado, que es captado por la cláusula catch.
Por el contrario, la siguiente definición de una nueva excepción está prohibida, ya que crea un tipo parametrizado:
Un intento de compilar lo anterior informa un error:
Esta restricción es sensata porque casi cualquier intento de detectar dicha excepción debe fallar, porque el tipo no es reificable. Uno podría esperar que un uso típico de la excepción sea algo como lo siguiente:
Esto no está permitido, porque el tipo en la cláusula catch no es reificable. Al momento de escribir este artículo, el compilador de Sun informa una cascada de errores de sintaxis en tal caso:
Como las excepciones no pueden ser paramétricas, la sintaxis está restringida, por lo que el tipo debe escribirse como un identificador, sin el siguiente parámetro.
fuente
Es esencialmente porque fue diseñado de mala manera.
Este problema impide un diseño abstracto limpio, por ejemplo,
El hecho de que una cláusula catch no funcione para los genéricos no está justificado no es excusa para ello. El compilador podría simplemente no permitir tipos genéricos concretos que extiendan Throwable o no permitir los genéricos dentro de las cláusulas catch.
fuente
EntityNotFoundException
. Pero eso haría que los genéricos sean inútiles.Los genéricos se verifican en tiempo de compilación para la corrección de tipo. La información de tipo genérico se elimina luego en un proceso llamado borrado de tipo . Por ejemplo,
List<Integer>
se convertirá al tipo no genéricoList
.Debido a la eliminación de tipo , los parámetros de tipo no se pueden determinar en tiempo de ejecución.
Supongamos que tiene permiso para extenderse
Throwable
así:Ahora consideremos el siguiente código:
Debido a la eliminación de tipo , el tiempo de ejecución no sabrá qué bloque de captura ejecutar.
Por lo tanto, es un error en tiempo de compilación si una clase genérica es una subclase directa o indirecta de Throwable.
Fuente: problemas con el borrado de tipo
fuente
Esperaría que sea porque no hay forma de garantizar la parametrización. Considere el siguiente código:
Como notará, la parametrización es solo azúcar sintáctico. Sin embargo, el compilador intenta asegurarse de que la parametrización permanezca consistente en todas las referencias a un objeto en el ámbito de compilación. En el caso de una excepción, el compilador no tiene forma de garantizar que MyException solo se arroje desde un ámbito que está procesando.
fuente