Java中的已检查和未检查的异常,这些断言是真的吗?

时间:2015-03-22 12:32:05

标签: java exception exception-handling

我对已检查的异常未经检查的异常之间的区别存有疑问。

我知道已检查异常通常代表无法直接控制程序的区域中的无效条件,例如无效的用户输入,数据库问题,网络中断,缺少文件,等

我也知道已检查异常异常抽象类的子类,方法有义务为其实现引发的所有已检查异常建立策略(要么将已检查的异常传递到堆栈中,要么以某种方式处理它。)

那么,在实践中,最后一个断言的确切含义是什么?

我可以简单地说在编译时检查已检查的异常。这意味着如果一个方法抛出一个已检查的异常,那么它应该使用 try-catch 块来处理异常,或者它应该使用 throws 关键字来声明异常,否则程序会给出编译错误。它被命名为检查异常,因为在编译时检查这些异常。

因此,如果某个方法抛出已检查的异常,我可以采用两种不同的方式处理它:

  1. 我必须将其处理为 try-catch 块,如下所示:

    try{
        //statements that may cause an exception
    } catch (exception(type) e(object))‏ {
        //error handling code
    }
    
  2. 使用方法声明中使用的 throws 关键字,以便显式指定特定方法可能抛出的异常。当方法声明使用throws子句定义了一个或多个异常时,方法调用必须处理所有已定义的异常。

    所以,如果我说错了断言,请纠正我, throws 关键字用于将检索到的已检查异常抛出到堆栈中的上层(进入调用者)。因此,如果一个方法调用另一个抛出一个检查过的异常的方法,如果它被抛出,则调用者方法必须处理它(例如通过 try catch 块)。这个推理是否正确?

    检查异常的缺点是引入了一种紧耦合的形式,因为如果我有一系列方法而最后一个抛出一个已检查的异常或我将其处理到其父代码中,或者所有中间方法必须通过方法声明中的 throws 关键字声明异常?这个断言是否正确?

  3. 相反,在编译时不会检查未经检查的异常。这意味着如果您的程序抛出未经检查的异常,即使您没有处理/声明该异常,程序也不会给出编译错误。大多数情况下,由于用户在用户程序交互期间提供的错误数据而发生这些异常。程序员可以提前判断条件,这可能导致这些异常并适当地处理它们。所有未经检查的异常都是RuntimeException类的直接子类。

    例如,我可以遇到这样的情况:

    class Example {  
       public static void main(String args[])
       {
        int num1=10;
        int num2=0;
        /*Since I'm dividing an integer with 0
         * it should throw ArithmeticException*/
        int res=num1/num2;
        System.out.println(res);
       }
    }
    

    编译这个类,编译器没有给我任何错误,但是运行它我将获得 ArithmeticException tath是一个未经检查的异常,因为它发生在运行时。

    所以我认为是开发人员必须处理这种情况,例如:

    class Example {  
       public static void main(String args[])
       {
        int num1=10;
        int num2=0;
        /*Since I'm dividing an integer with 0
         * it should throw ArithmeticException*/
        try {
            int res=num1/num2;
        } catch(ArithmeticException e) {
             System.out.println("Division for 0, this is not a good idea !!!");
        }
    
        System.out.println(res);
       }
    }
    

    所以我怀疑是:

    1. 在我看来,对于未经检查的例外,我也可以使用 try catch 块。那么在已检查的异常未经检查的异常之间使用 try catch 块的区别是什么?是否只有检查异常我必须使用它(或在方法声明中使用 throws 关键字)否则我将获得编译时错误消息?

    2. 此外,未经检查的异常会自动传播到上级进入方法调用的堆栈吗?

    3. TNX

3 个答案:

答案 0 :(得分:2)

关于throws引入的耦合,你是绝对正确的:throws子句中声明的异常成为方法的公共接口的一部分(一般意义上)这个词;不考虑Java的接口和公共访问)。但是,这种耦合与通过声明返回类型或方法的参数类型引入的耦合没有什么不同。您可以将其视为方法签名的第三个属性。

  

在我看来,我也可以将try catch块用于未经检查的异常。那么在已检查的异常和未经检查的异常之间存在的try catch块的使用有何不同?

您当然可以捕获未经检查的异常,但您应该在程序的最顶层执行此操作以防止完全崩溃。未经检查的异常表示编程错误,因此您无法以有意义的方式处理它们。你能做的最好的就是记录它们,继续前进。

  

此外,未经检查的异常会自动传播到上级到方法调用的堆栈中吗?

是的,它们以与throws子句中声明异常并且未被捕获的异常相同的方式执行此操作。

答案 1 :(得分:1)

  1. 是。您可以使用try catch块来捕获未经检查的异常以及已检查的异常。

  2. 所有例外情况,无论是已选中还是未选中,如果未被捕获,都会传播到下一级别。

  3. 不同之处在于,如果方法可以抛出已检查的异常E(因为它调用throws E的方法,或者因为它直接使用语句throw E抛出它,方法声明必须使用throws E包含此信息。

    因此,如果您想调用可以抛出已检查异常E的方法,必须将方法调用放在try块中或声明{{1} }。对于未经检查的例外,这些内容是可选的。

    大多数情况下,您不应该捕获未经检查的异常。

答案 2 :(得分:0)

  1. 未检查和已检查异常的try catch之间没有区别。如你所说。

    - 如果方法使用另一种可能抛出已检查异常的方法,则下列两项内容之一应为真: 该方法应该包含在try-catch块中,或者该方法应该指定在其方法签名中抛出此异常。

    - 未经检查的异常可能不是方法签名的一部分,即使是 方法可以抛出它。

  2. 当一段代码以异常条件的形式遇到障碍时,它会创建类java.lang.Throwable的对象。 Checked和Unchecked Exceptions通过方法调用传播,因为它们都是子类java.lang.Throwable。