为什么这样说:“已检查的异常不在调用链中已传播转发”?

问题描述

对于未检查的(运行时)异常,这是可以理解的。它们实际上是通过堆栈传播的。但是为什么说检查异常不是?是的,我们必须声明(抛出)或处理(尝试捕获),但是为什么在这种情况下不称为“传播”呢?让我给你一个基本的例子:

public class Main {
    void m() throws IOException {
        throw new java.io.IOException("device error");//checked exception
    }
    void n() throws IOException {
        m();
    }
    void p(){
        try{
            n();
        }catch(Exception e){System.out.println("exception handled");}
    }
    
    public static void main(String args[]){
        new Main().p();
    }
}

我认为我只是做了一个很好的“链式”操作。那么,为什么文档说“认情况下不传播”?

解决方法

默认情况下不传播

我相信这是here的来源。

这是不寻常的术语。 我怀疑那句话的意思是你不能只写:

void m() {
    throw new IOException("device error");//checked exception
}
void n() {
    m();
}
void p(){
    try{
        n();
    }catch(Exception e){System.out.println("exception handled");}
}

因为该异常不是从m()n()p()的“传播”,因为这是一个已检查的异常,所以该代码甚至无法编译。

如果这是未经检查的异常,它将通过此​​代码从m()n()p()传播。

如果这是您想要的,则必须显式传播异常:

void m() throws IOException { ... }
void n() throws IOException { m(); }

这种传播的替代方法是在方法内部进行处理。关键是,您必须选择处理它。

,

在运行时,检查和未检查异常的行为实际上根本没有区别。

检查的异常只是所有异常的子集,编译器会决定对其进行检查,并查看是否将它们明确声明为抛出或捕获。如果没有,那就是错误。

如果您能以某种方式hack the compiler to skip this check,它的行为就像运行时一样。

鉴于运行时语义是相同的,因此说一个被传播而另一个不传播是没有道理的。