【问题标题】:Checked Exception 2 kinds of behavioursChecked Exception 2种行为
【发布时间】:2013-09-22 16:38:06
【问题描述】:

我注意到有两种检查异常:

1)

public static void main (String []args)
{
    try{
        //no exception thrown here, it still compiles though.
    }
    catch(Exception e){System.out.println(e);}
}

2)

public static void main (String []args)
{
    try{
         // it does not compile if not written any code which potentially might throw it
    }
    catch(IOException io){System.out.println(io);}
}

是否有任何规则可以预测这种行为?提前知道哪些不是必须在场的吗? 希望我已经很清楚地解释了这个问题。 谢谢, 确实是

【问题讨论】:

    标签: java exception checked


    【解决方案1】:

    Java Language specification 状态

    如果catch 子句可以catch 被检查,这是一个编译时错误 异常类 E1 并且 try 块不是这种情况 对应catch子句可以抛出检查异常类 是 E1 的子类或超类,除非 E1 是 Exception 或 异常的超类。

    【讨论】:

    • 我相信这是因为Exception 包含运行时异常。这就是我在回答中试图说的。不是这样吗?
    • @NickC Exception 可能是所有未检查异常的超类,但它本身并不是未检查异常。这是一个检查异常。
    • 正确,我不是说它是。我建议您的答案中出现该子句的原因是因为它是所有运行时异常的超类;因此它无法计算是否可以捕获 Exception 的编译时分析。
    • @nickC 调用声明为throws Exception的方法可以,否则遵循JLS。
    • 现在你失去了我。它可以知道它是否可能,但是编译器不能确定它是不可能可能的。
    【解决方案2】:

    代码使用Exception 编译得很好,因为它是所有CheckedUnchecked 异常的超类。因此,带有Exceptioncatch 子句也可以处理未经检查的异常。对于未经检查的异常,编译器无法在编译时检查是否抛出了异常。因此,Exception 不会出现任何错误。

    你甚至可以用RuntimeException试试这个:

    try {
    
    } catch (RuntimeException e) {
    
    }
    

    ...这也将编译。

    来自JLS Section 11.2.3 - Exception Checking

    如果catch 子句可以捕获已检查的异常类E1,并且与catch 子句对应的try 块不能抛出作为E1 的子类或超类的已检查异常类,则这是编译时错误,除非 E1 是 Exception 或 Exception 的超类。

    【讨论】:

    • 是的,但Exception 不是未经检查的异常。如果它被扔到身体里,你仍然必须抓住它。
    • @SotiriosDelimanolis。是啊,没错。但它也可以处理未经检查的异常。我说,它是所有已检查和未检查异常的超类。这是由于未经检查的子类异常而编译的。
    • @SotiriosDelimanolis。我正在JLS中寻找确切的原因,如果找到会发布。
    • 在下面查看我的回答和docs.oracle.com/javase/specs/jls/se7/html/…
    • @SotiriosDelimanolis。糟糕,我正在编辑时错过了您的评论。
    【解决方案3】:

    Exception 本身是一个已检查异常,但也是 RuntimeException 和其他未检查异常的超类。

    1) 在第一种情况下,因为Exception 类层次结构包括RunTimeException,编译器不能断定Exception不会被抛出你的try { ... } 块。所以,它必须允许代码。

    它可以确认肯定情况(如果你调用声明throws Exception或非运行时子类的方法),但不能确认否定情况。

    2) 在第二种情况下,它可以在编译时得出结论,IOException 不会被抛出try { ... } 块,因为IOException (除了Exception 本身之外,也没有任何其他已检查异常)不是任何运行时异常的超类。


    在以下行为中,我认为Exception是唯一一种结合了两种类型的特殊情况:

    如果抛出:
    1A.不需要声明 1B.必须声明

    如果声明:
    2A.不需要抛出 2B.必须扔掉

    如果不扔:
    3A.可能会被抓住 3B.不能被抓到

    • RuntimeException:1A2A3A
    • 任何其他已检查的异常:1B2B3B
    • 例外:1B2A3A

    此答案中有关已检查与未检查异常的更多信息:https://stackoverflow.com/a/6116020/143295

    【讨论】:

    • @SotiriosDelimanolis 谢谢,我正在更新我的答案,以澄清 Exception 本身已被检查,但它是未检查异常的父类,遵循我们的 cmets 对您的回答。顺便说一句,答案很好。
    • @SotiriosDelimanolis 谢谢,我今天学到了一些东西。我更新了答案以描述我在运行测试代码时看到的情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-31
    • 1970-01-01
    • 2011-02-05
    • 2016-07-14
    • 1970-01-01
    相关资源
    最近更新 更多