为什么会说:“在调用链中不会转发(传播)已检查异常?”

huangapple go评论80阅读模式
英文:

Why is it said: "Checked exceptions are not forwarded in calling chain (propagated)"?

问题

对于未经检查的(运行时)异常是可以理解的。它们会通过堆栈传播。但为什么说检查异常不会呢?是的,我们必须声明(使用throws)或者处理它们(使用try-catch),但为什么在这种情况下不称其为“传播”呢?让我给你一个基本的例子:

public class Main {
    void m() throws IOException {
        throw new java.io.IOException("设备错误");//检查异常
    }
    void n() throws IOException {
        m();
    }
    void p(){
        try{
            n();
        }catch(Exception e){System.out.println("异常已处理");}
    }
    
    public static void main(String args[]){
        new Main().p();
    }
}

我认为我只是做了一个良好的“链接”。那么为什么文档说“默认情况下,检查异常不会被传播”呢?

英文:

For unchecked (runtime) exceptions it is understandable. They are literally propagated through stack. But why is it said that checked exceptions are not? Yes, we have to declare (throws) or handle them (try-catch), but why is it not called 'propagating' in this case? Let me give you basic example:

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();
    }
}

In my opinion I just did a 'chaining' that worked fine. So why do the docs say "by default checked are not propagated"?

答案1

得分: 4

> 默认情况下,已检查异常不会被传播。

我认为这个问题的源代码在这里

这个术语用法很不寻常。
我怀疑这个陈述的意思是,你不能只是写下:

void m() {
    throw new IOException("设备错误");//已检查异常
}
void n() {
    m();
}
void p(){
    try{
        n();
    }catch(Exception e){System.out.println("异常已处理");}
}

因为异常没有从m()传播到n()再到p(),因为它是一个已检查异常,所以这段代码甚至无法编译。

如果它是一个未经检查的异常,那么它会从m()传播到n()再到p(),就像这段代码一样。

如果你想要这样做,你必须明确地传播异常:

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

与此传播的替代方法是在方法内部处理它。关键是,你必须选择如何处理它。

英文:

> by default checked are not propagated

I believe the source of this is here.

This is unusual terminology.
I suspect what is meant by that statement is that you can't just write:

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

because the exception isn't "propagated" from m() to n() to p(), because it's a checked exception, so this code doesn't even compile.

It would be "propagated" from m() to n() to p() by this code if it were an unchecked exception.

You have to explicitly propagate the exception, if that's what you want:

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

The alternative to such propagation is that you handle it inside the method. The point is, you have to choose what to do with it.

答案2

得分: 2

以下是翻译好的部分:

实际上,在运行时,检查异常和非检查异常的行为没有任何区别。

检查异常只是所有异常的一个子集,编译器决定查看它们,并查看它们是否被明确声明为被抛出或被捕获。如果没有,就会报错。

如果你可以以某种方式欺骗编译器以跳过此检查,它的行为就完全像运行时异常一样。

鉴于运行时语义是相同的,说其中一个是传播的,另一个不是传播的是没有意义的。

英文:

There is actually no difference at all between the behaviour of checked and unchecked exceptions at runtime.

Checked exceptions are merely a subset of all exceptions, for which the compiler decides to look at them and see whether they are either explicitly declared as thrown or caught. If not, it's an error.

If you can somehow hack the compiler to skip this check, it behaves exactly like a runtime one.

Given the runtime semantics are identical, it does not make sense to say one is propagated and the other isn't.

huangapple
  • 本文由 发表于 2020年9月1日 23:20:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/63690622.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定