De acordo com o Java Language Sepecification , 3ª edição:
Desejo entender por que essa decisão foi tomada. O que há de errado com exceções genéricas?
(Até onde eu sei, os genéricos são simplesmente açúcar sintático em tempo de compilação e serão traduzidos de Object
qualquer maneira nos .class
arquivos, declarar com eficiência uma classe genérica é como se tudo nela fosse um Object
. Por favor, corrija-me se estiver errado .)
java
generics
exception
language-design
Hosam Aly
fonte
fonte
myList.get(i)
, obviamenteget
ainda retorna umObject
. O compilador insere uma conversãoA
para capturar algumas das restrições no tempo de execução? Caso contrário, o OP está certo de que, no final, se resume aObject
s no tempo de execução. (O arquivo de classe certamente contém metadados sobreA
, mas é apenas metadados AFAIK.)Respostas:
Como mark disse, os tipos não são passíveis de devolução, o que é um problema no seguinte caso:
Ambos
SomeException<Integer>
eSomeException<String>
são apagados para o mesmo tipo, não há como a JVM distinguir as instâncias de exceção e, portanto, não há como saber qualcatch
bloco deve ser executado.fonte
Aqui está um exemplo simples de como usar a exceção:
O corpo da instrução TRy lança a exceção com um determinado valor, que é capturado pela cláusula catch.
Por outro lado, a seguinte definição de uma nova exceção é proibida, pois cria um tipo parametrizado:
Uma tentativa de compilar o que foi mencionado acima relata um erro:
Essa restrição é sensata porque quase qualquer tentativa de capturar essa exceção deve falhar, porque o tipo não é reificável. Pode-se esperar que um uso típico da exceção seja algo como o seguinte:
Isso não é permitido, porque o tipo na cláusula catch não é reificável. No momento da redação deste artigo, o compilador Sun reporta uma cascata de erros de sintaxe nesse caso:
Como as exceções não podem ser paramétricas, a sintaxe é restrita, de modo que o tipo deve ser gravado como um identificador, sem o seguinte parâmetro.
fonte
É essencialmente porque foi projetado de uma maneira ruim.
Esse problema impede o design abstrato limpo, por exemplo,
O fato de uma cláusula catch falhar para genéricos não é reificado não é desculpa para isso. O compilador pode simplesmente proibir tipos genéricos concretos que estendem Throwable ou desautorizar genéricos dentro de cláusulas catch.
fonte
EntityNotFoundException
. Mas isso tornaria os genéricos inúteis.Os genéricos são verificados no momento da compilação quanto à correção do tipo. As informações de tipo genérico são removidas em um processo chamado apagamento de tipo . Por exemplo,
List<Integer>
será convertido para o tipo não genéricoList
.Por causa do apagamento do tipo , os parâmetros do tipo não podem ser determinados em tempo de execução.
Vamos supor que você tenha permissão para estender
Throwable
assim:Agora vamos considerar o seguinte código:
Devido ao apagamento do tipo , o tempo de execução não saberá qual bloco de captura executar.
Portanto, é um erro em tempo de compilação se uma classe genérica for uma subclasse direta ou indireta de Throwable.
Fonte: Problemas com apagamento de tipo
fonte
Eu esperaria que seja porque não há como garantir a parametrização. Considere o seguinte código:
Como você observa, a parametrização é apenas açúcar sintático. No entanto, o compilador tenta garantir que a parametrização permaneça consistente em todas as referências a um objeto no escopo da compilação. No caso de uma exceção, o compilador não tem como garantir que MyException seja lançada apenas de um escopo que está processando.
fonte