web-dev-qa-db-fra.com

Java lève une exception mais l'implémentation d'interface ne lève pas d'exception?

J'ai lu ce code où l'interface lève une exception, mais la classe qui l'implémente n'en lève pas ou n'en attrape pas, pourquoi? Est-ce légal ou sûr 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();
        }
    }
}
44
Al2O3

Une règle générale d'implémentation et d'extension est que vous pouvez rendre votre nouvelle classe ou interface "moins restrictive" mais pas "plus restrictive". Si vous considérez la nécessité de gérer une exception comme une restriction, une implémentation qui ne déclare pas l'exception est moins restrictive. Quiconque code sur l'interface n'aura aucun problème avec votre classe.

- Stan James


Dans le cadre de la discussion sur http://www.coderanch.com/t/399874/Java/java/Methods-throwing-Exception-Interface

69
Chetter Hummin

Si une méthode Java remplace une autre dans une classe parente ou implémente une méthode définie dans une interface, elle peut ne pas lever d'exceptions vérifiées supplémentaires, mais elle peut en générer moins.

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

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

SQLException est très bien; il est déclaré dans la méthode substituée. Il pourrait même être remplacé par une sous-classe comme SerialException.

RuntimeException est très bien; ceux-ci peuvent être utilisés n'importe où.

NamingException est illégal. Ce n'est pas un RuntimeException et n'est pas dans la liste de A, même en tant que sous-type.

17
Eric Jablow

Grande réponse de @Chetter Hummin.

Une façon de voir les choses, et je trouve cela facile à retenir, est que les implémentations de l'interface peuvent être plus spécifiques mais pas plus générales.

Par exemple, dans l'interface void test() throws Exception signifie "le test peut lever l'exception"

alors l'implémentation peut être void test() signifie "le test ne lèvera pas d'exception" (plus spécifique)

ou l'implémentation peut être void test() throws NullpointerException (plus spécifique)

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
    }
}
1
Foolish