声明 - 抛出与抛出 - 没有被声明的异常

时间:2008-11-21 18:57:56

标签: java exception

在Java中,双方法有什么区别?

public void methodA() throws AnException {
    //do something
    throw new AnException();
}

public void methodA() {
    //do the same thing
    throw new AnException();
}

我有一种直觉,认为它与设计良好的方法有关(因为我将methodA放在一个接口中,声明它就像方法A *在其实现中所做的那样,并从Java收到警告“A *不能覆盖A因为A *不抛出AnException“)。

这种推测是否正确?

这两种做事方式还有其他微妙的含义吗?

5 个答案:

答案 0 :(得分:13)

如果AnException是一个已检查的异常(换句话说,如果它没有扩展RuntimeException),那么methodA将不会编译。必须始终对已检查的异常进行分解。

如果AnException是未经检查的异常(如果它确实扩展了RuntimeException),那么java编译器允许任何一个异常,并且java运行时等同地解释它们。 出于文档的原因,在这种情况下,methodA仍然可能仍然是首选。您的方法的javadoc将显示它可能会抛出AnException。让方法的用户知道他们应该期待什么样的例外情况是很好的。

答案 1 :(得分:2)

除了其他人给出的关于你自己的方法的可编译性的好答案之外,还有在超类中实现接口和覆盖方法的问题。

规则说您可以覆盖/实现方法,但您不能向原始方法签名声明的那些声明额外的异常。要理解这一点,请考虑这个例子。

假设您正在使用某种数据结构:

public abstract class AbstractBox {
  public abstract void addItem(Item newItem);
  public abstract void removeItem(Item oldItem);
}

您有自己的实现,但您决定声明未出现在原始签名中的异常:

public class MyBox extends AbstractBox {
  public void addItem(Item newItem) throws ItemAlreadyPresentException {...}
  public void removeItem(Item oldItem) throws NoSuchItemException {...}
}

现在让我们考虑这个处理Box对象的通用代码,并接收MyBox的实例:

public void boxHandler(AbstractBox box) {
  Item item = new Item();
  box.removeItem(item);
}

编写此代码的人不会期待任何异常,也不打算处理实现者异常。为了防止这种情况,编译器将不允许您向原始签名中的那些声明其他异常。

当然,如果您在内部处理异常......那么,编译器将非常乐意允许您从签名中删除声明的异常; - )

希望这会有所帮助......

Yuval = 8 - )

答案 2 :(得分:1)

必须在try catch块或声明抛出AnException的方法中调用第一个方法 否则编译将失败。

第二个没有这样的限制

答案 3 :(得分:0)

在第二种方法中,AnException类需要是RuntimeException的子类,这意味着声明不是必需的,方法调用者不必处理它。 RuntimeException的一个示例是ArrayOutOfBoundException,想象一下,如果您每次使用List时都显式处理异常(通过声明抛出或使用try / catch块)。

答案 4 :(得分:0)

出于纯文档原因,函数定义中包含异常是很好的。通过这种方式,调用者可以清楚地知道需要处理哪些异常。我也猜测编译器需要为抛出异常的函数做一些高级设置。