Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

Porque posso mudar a assinatura do método com anotação @Override sem gerar erro de compilação?

O método close da classe abaixo é assinado com @Override. Segundo a explicação do professor ele deveria ter a mesma assinatura do método sobrescrito, caso contrário não compilaria.

Porém o código sobrescrito da interface AutoCloseable tem um throws Exception que é retirado sem gerar erro de compilação. Podem explicar essa exceção à regra?

Obrigado

Código da interface AutoCloseable:

    void close() throws Exception;

Código sobrescrito (na verdade implementado) na classe Conexão.

public class Conexao implements AutoCloseable {

    public Conexao() {
        System.out.println("Abrindo Conexão");
        throw new IllegalStateException();

    }

    public void leDados() {
        System.out.println("Recebendo dados");
        throw new IllegalStateException();
    }

    @Override
    public void close() {
        System.out.println("Fechando conexão");

    }
}
2 respostas

Olá Daniel, tudo bem?

Na verdade a regra para sobrescrever/implementar um método, de acordo com o que geralmente aprendemos, é que deve ter a mesma assinatura do método da classe pai/interface (ou seja, ter o mesmo nome e os mesmos parâmetros - respeitando rigorosamente ordem e tipos), além do mesmo tipo de retorno.

Contudo, há um complemento a essa regra que é o que causa, à primeira vista, uma certa confusão. O método sobrescrito pode modificar a lista de exceções declaradas, o modificador de acesso e/ou o tipo de retorno, desde que nenhuma dessas mudanças force o chamador do método algum tratamento diferente do que foi estabelecido na interface/classe pai.

Pense assim. Quem está chamando o método sabe que ele tem aquele tipo de retorno, está acessível de acordo com determinado nível de acesso e pode lançar alguma daquela lista de exceções definidas. Portanto, esse é o mínimo, e que deve ser respeitado. Se eu vou sobrescrever esse método e falo que o retorno em vez de String é um int, não é uma sobrescrita, pois int não tem nada a ver com String. Da mesma forma, se eu falar que além de Exception o método também lança SQLException, viola o mínimo que foi combinado, pois um SQLException é do tipo "checked" e obriga algum tipo de tratamento. Por fim, se um método está como "protected", eu não posso sobrescrever e mudar para "private", pois assim estou reduzindo o nível de acesso do método, o que também é inválido, pois o "mínimo" é que ele seja "protected".

Dito isso, então as possibilidades abaixo são válidas:

  • Você pode remover declaração de exceções do seu método sobrescrito (como o do seu exemplo). Inclusive, você pode até acrescentar outras, desde que sejam unchecked, pois unchecked exceptions não exigem um tratamento;

  • Você pode mudar o tipo de retorno do seu método para um tipo que passe pelo teste "is-a". Ou seja, se o método da interface/classe pai é do tipo Number, você mudar o retorno para BigDecimal, pois BigDecimal is-a Number. Detalhe aqui: https://docs.oracle.com/javase/tutorial/java/javaOO/returnvalue.html;

  • Você pode aumentar o nível de acesso do seu método, mas nunca reduzir. Ou seja, se o método está declarado como "protected", no método sobrescrito pode estar como "public". Mais detalhe aqui: https://docs.oracle.com/javase/tutorial/java/IandI/override.html

Espero ter ajudado.

Abraços!

solução!

Excelente resposta. Agora ficou bem claro. Muito obrigado.