Esta regra tem como objetivo evitar conflitos no código legado que ainda usa tipos brutos.
Aqui está uma ilustração de por que isso não foi permitido, extraído do JLS. Suponha que, antes de os genéricos serem introduzidos no Java, eu escrevi um código como este:
class CollectionConverter {
List toList(Collection c) {...}
}
Você estende minha classe, assim:
class Overrider extends CollectionConverter{
List toList(Collection c) {...}
}
Após a introdução dos genéricos, decidi atualizar minha biblioteca.
class CollectionConverter {
<T> List<T> toList(Collection<T> c) {...}
}
Você não está pronto para fazer atualizações; portanto, deixe sua Overrider
turma em paz. Para substituir o toList()
método corretamente , os designers de linguagem decidiram que um tipo bruto era "equivalente a substituição" para qualquer tipo gerado. Isso significa que, embora sua assinatura de método não seja mais formalmente igual à assinatura da minha superclasse, seu método ainda substitui.
Agora, o tempo passa e você decide que está pronto para atualizar sua turma. Mas você estraga um pouco e, em vez de editar o toList()
método bruto existente, adiciona um novo método como este:
class Overrider extends CollectionConverter {
@Override
List toList(Collection c) {...}
@Override
<T> List<T> toList(Collection<T> c) {...}
}
Devido à equivalência de substituição dos tipos brutos, os dois métodos estão em uma forma válida para substituir o toList(Collection<T>)
método. Mas é claro que o compilador precisa resolver um único método. Para eliminar essa ambiguidade, as classes não têm permissão para ter vários métodos que são equivalentes a substituição - ou seja, vários métodos com os mesmos tipos de parâmetro após a exclusão.
A chave é que essa é uma regra de idioma projetada para manter a compatibilidade com o código antigo usando tipos brutos. Não é uma limitação exigida pelo apagamento dos parâmetros de tipo; como a resolução do método ocorre no tempo de compilação, a adição de tipos genéricos ao identificador do método seria suficiente.