61

我读了这段代码,其中接口抛出了一个异常,但是实现它的类没有抛出一个或捕获一个,这是为什么呢?在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();
        }
    }
}
4

3 回答 3

85

实现和扩展的一般规则是您可以使您的新类或接口“限制更少”,但不能“限制更多”。如果您将处理异常的要求视为限制,则不声明异常的实现限制较少。任何对接口进行编码的人都不会在您的课程中遇到麻烦。

— 斯坦·詹姆斯


作为http://www.coderanch.com/t/399874/java/java/Methods-throwing-Exception-Interface讨论的一部分

于 2013-03-25T03:24:32.567 回答
24

如果一个 Java 方法覆盖了父类中的另一个方法,或者实现了接口中定义的方法,它可能不会抛出额外的检查异常,但它可能会抛出更少的异常。

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

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

SQLException很好;它在被覆盖的方法中声明。它甚至可以被一个像SerialException.

RuntimeException很好;那些可以在任何地方使用。

NamingException是非法的。它不是RuntimeException,也不在A的列表中,即使作为子类型也是如此。

于 2013-03-25T03:29:34.927 回答
9

@Chetter Hummin 的好回答。

一种看待这一点的方法,我发现它很容易记住,接口的实现可以更具体,但不能更通用。

例如在接口中void test() throws Exception表示“测试可能抛出异常”

那么实现可以void test()意味着“测试不会抛出异常”(更具体)

或实施可以void test() throws NullpointerException(更具体)

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
    }
}
于 2018-06-21T11:15:34.950 回答