在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“)。
这种推测是否正确?
这两种做事方式还有其他微妙的含义吗?
答案 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)
出于纯文档原因,函数定义中包含异常是很好的。通过这种方式,调用者可以清楚地知道需要处理哪些异常。我也猜测编译器需要为抛出异常的函数做一些高级设置。