到目前为止,我认为必须由构造函数在某处创建每个Java异常,因为我可以自己创建自定义异常:
throw new Exception();
但现在看来我必须处理JavaMail中的一些异常 - MessagingException。它来自方法Store.close
(继承自Service
类)。
我去了那里(我需要检查什么时候抛出这个异常所以我知道什么是错的)我看到这个方法调用了另外两个方法 - 它们都没有抛出异常!
public synchronized void close() throws MessagingException {
setConnected(false);
notifyConnectionListeners(ConnectionEvent.CLOSED);
}
据我所知,这是检查Exception(既不是Error也不是RuntimeException),那么怎么可能不必在close
方法命令的任何使用中声明它?在这种方法中也没有创建它。
答案 0 :(得分:3)
声明的异常并不是 实现可以抛出的内容 - 它是关于该实现或子类中的实现可以抛出的内容。 Service
是一个抽象类 - JavaMail(Transport
和Store
)实现的两个直接子类也是如此。即使那些都没有覆盖close()
,您使用的具体实现仍可能会覆盖close()
和其实施可能会抛出MessagingException
。
从API设计的角度来看,它是否有意义?我必须更密切地关注JavaMail对此的任何判断,谢天谢地,我已经很长时间不必使用JavaMail了。
从语言角度是否有意义?绝对。拥有一个不会抛出特定已检查异常的实现是完全合理的,但预计具体的子类可能需要这样做。
答案 1 :(得分:2)
关于method declaration的JLS说
声明已检查异常的要求允许Java编译器确保已包含用于处理此类错误条件的代码。如果方法或构造函数在其throws子句中缺少适当的异常类型,则无法处理在其正文中作为已检查异常抛出的异常条件的方法或构造函数通常会导致编译时错误。因此,Java编程语言鼓励编程风格,以这种方式记录罕见的和其他真正特殊的条件。
基本上,如果不处理异常,您确定代码将无法编译。因此,即使它没有在此实现中抛出,它也可能位于子类中。
阅读整页以获取更详细的信息。
Mother m = new Daughter();
因为这是有效的
m.foo(); //will not compile
你失去了实例的真实类型,所以幸运的是编译器会在你做
时尖叫throws
请注意,如果子类中的覆盖方法需要throws
,则不能使用任何throws
声明的母语方法。它是禁止的,你不能在子类{{1}}声明中添加或使用超类的异常