¿La interfaz Java lanza una excepción pero la implementación de la interfaz no lanza una excepción?


Leo este código donde la interfaz lanza una excepción, pero la clase que la implementa no lanza una o atrapa una, ¿por qué? ¿Es legal o seguro en Java?

import java.rmi.*;
public interface MyRemote extends Remote {
    public String sayHello() throws RemoteException;
}

import java.rmi.*;
import java.rmi.server.*;
public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote{
    public String sayHello() {
        return "Server says, 'Hey'";
    }
    public MyRemoteImpl() throws RemoteException {}
    public static void main (String[] args) {
        try {
             MyRemote service = new MyRemoteImpl();
             Naming.rebind("RemoteHello", service);
        } catch(Exception ex)
        {
            ex.printStackTrace();
        }
    }
}
Author: Morgan Kenyon, 2013-03-25

3 answers

Una regla general para implementar y extender es que puede hacer que su nueva clase o interfaz sea "menos restrictiva" pero no "más restrictiva". Si considera que el requisito de manejar una excepción es una restricción, una implementación que no declare la excepción es menos restrictiva. Cualquiera que codifique en la interfaz no tendrá problemas con su clase.

- Stan James


Como parte de la discusión en http://www.coderanch.com/t/399874/java/java/Methods-throwing-Exception-Interface

 52
Author: Chetter Hummin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-28 12:05:25

Si un método Java anula otro en una clase padre, o implementa un método definido en una interfaz, no puede lanzar excepciones verificadas adicionales, pero puede lanzar menos.

public class A {
    public void thrower() throws SQLException {...}
}

public class B extends A {
    @Override
    public void thrower() throws SQLException, RuntimeException, NamingException {...}
}

SQLException está bien; se declara en el método anulado. Incluso podría ser reemplazado por una subclase como SerialException.

RuntimeException está bien; se pueden usar en cualquier lugar.

NamingException es ilegal. No es un RuntimeException, y no está en la lista de A, incluso como un subtipo.

 12
Author: Eric Jablow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-28 12:06:20

Gran respuesta de @Chetter Hummin.

Una forma de ver esto, y me parece fácil de recordar, es que las implementaciones de interface pueden ser más específicas pero no más generales.

Por ejemplo en interfaz void test() throws Exception significa "prueba puede lanzar excepción"

Entonces la implementación puede ser void test() significa "prueba no lanzará excepción" (más específico)

O la implementación puede ser void test() throws NullpointerException (más específica)

interface x {
    void testException() throws Exception;
}

public class ExceptionTest implements x {
    @Override
    public void testException() {   //this is fine
    }

    ////// or

    @Override
    public void testException() throws NullPointerException {  // this is fine
    }
}
 0
Author: Foolish,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-21 11:15:34