Java 异常从何而来?

Where do Java exceptions came from?

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

throw new Exception();

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

我去了那里(我需要检查什么时候抛出这个异常,这样我就知道可能出了什么问题),我看到这个方法调用了另外两个方法 - none 其中抛出了一个异常!

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

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

关于 method declaration 的 JLS 说

The requirement to declare checked exceptions allows a Java compiler to ensure that code for handling such error conditions has been included. Methods or constructors that fail to handle exceptional conditions thrown as checked exceptions in their bodies will normally cause compile-time errors if they lack proper exception types in their throws clauses. The Java programming language thus encourages a programming style where rare and otherwise truly exceptional conditions are documented in this way.

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

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

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

请注意,如果 subclass 中的重写方法需要 throws 某些内容,则您不能在没有任何 throws 声明的情况下使用来自 mother 的方法。这是禁止的,您不能在 subclass throws 声明

中添加或使用异常的 super class

声明的异常与那个实现可以抛出什么无关——它是关于那个实现或子classes中的实现 可以扔。 Service 是一个抽象 class - JavaMail 实现的两个直接子 class 也是如此(TransportStore)。即使 those 都没有覆盖 close(),您使用的具体实现仍然完全有可能覆盖 close()its 实现可能会抛出 MessagingException.

从 API 设计角度来看是否有意义?我必须更仔细地研究 JavaMail 才能对此作出任何判断,幸好我已经很长时间没有使用 JavaMail 了。

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