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();
}
}
}
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
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.
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
}
}