1

到目前为止,我认为每个 Java 异常都必须由构造函数在某处创建,因为我可以自己创建自定义异常:

throw new Exception();

但现在看来我必须处理来自 JavaMail - MessagingException的一些异常。它来自方法(从类Store.close继承)。Service

我去了那里(我需要检查什么时候抛出这个异常,这样我才能知道哪里出了问题),我看到这个方法调用了另外两个方法——它们都没有抛出异常!

public synchronized void close() throws MessagingException {
    setConnected(false);
    notifyConnectionListeners(ConnectionEvent.CLOSED);
}

据我了解,这是检查异常(既不是错误也不是 RuntimeException),那么它怎么可能不必在close方法命令使用的任何一个中声明呢?它也不是在此方法中创建的。

4

2 回答 2

3

声明的异常与实现可以抛出什么无关 - 它与该实现或子类中的实现可以抛出什么有关。是一个抽象类 - JavaMail (和)Service实现的两个直接子类也是如此。即使这些都没有覆盖,您使用的具体实现仍然完全有可能覆盖并且它的实现可能会抛出。TransportStoreclose()close()MessagingException

从 API 设计的角度来看,这有意义吗?我必须更仔细地查看 JavaMail 才能对此做出判断,谢天谢地,我已经很长时间没有使用 JavaMail 了。

从语言的角度来看是否有意义?绝对地。有一个不抛出特定检查异常但预期具体子类可能需要的实现是完全合理的。

于 2017-05-16T11:32:09.857 回答
2

关于方法声明的 JLS说

声明检查异常的要求允许 Java 编译器确保包含用于处理此类错误条件的代码。如果方法或构造函数无法处理在其主体中作为已检查异常抛出的异常条件,则如果它们的 throws 子句中缺少适当的异常类型,则通常会导致编译时错误。因此,Java 编程语言鼓励一种以这种方式记录罕见和真正异常情况的编程风格。

基本上,如果不处理异常,您可以确定代码不会编译。所以即使它没有在这个实现中抛出,它也可能在一个子类中。

阅读整页以获取更多详细信息。

public class Mother{
    public foo() throws Exception{
         system.out.println("I am mother");
    }
}

public class Daughter extends Mother{

    @Override
    public foo() throws Exception{
         throws new Exception("I am a teenager !!");
    }
}

由于这是允许的

Mother m = new Daughter();

你失去了实例的真实类型,所以幸运的是,如果你这样做了编译器会尖叫

m.foo(); //will not compile

throws请注意,如果子类中的重写方法需要某些东西,则不能在没有任何声明的情况下从母亲那里获得方法throws。禁止,不能在子类throws声明中添加或使用异常的超类

于 2017-05-16T10:33:46.207 回答