【问题标题】:Why "catch" block necessarily requres an exception type?为什么“catch”块必然需要异常类型?
【发布时间】:2015-08-16 08:34:25
【问题描述】:

在java中的异常处理方面,我已经看到所有try-catch块都需要一种它必须处理的异常,更常见的是:

 catch(Exception e){
 System.out.println("Error occured");
}

现在我的问题是为什么它需要Exception e,因为它没有在任何地方使用?

关于我刚刚编写的以下代码的第二个问题

Scanner scanner = new Scanner(System.in);
    int x = 1;

    do {
        try {

            System.out.println(" Enter your first number:");
            int n1 = scanner.nextInt();
            System.out.println(" Enter your second number:");
            int n2 = scanner.nextInt();
            int result = n1 / n2;
            System.out.println("");
            System.out.println("The result is : " + result);
            x = 2;

        } catch (ArithmeticException arithmeticException) {
            System.out.println("Error occured");

        }

    } while (x == 1);

}

在上面的代码中,我看到该程序可以使用catch (ArithmeticException arithmeticException)catch(Exception e) 两个参数。 那么这两种不同类型的错误如何处理同一个代码块呢?

【问题讨论】:

  • 异常是对象,而您的“自定义”异常只是该通用异常的后代。 ALL 异常可以被通用catch (Exception e) 捕获,但您也可以有多个捕获块,每个捕获块中的一个。例如catch (FailedAssertion e)catch(FileNotFound e),等等等等。
  • 你不需要捕捉Exception,你可以捕捉Throwable,它是ExceptionError的超类。但是,应该注意的是,大多数Errors 并不是真的要被抓住(例如OutOfMemoryError);您可能想在它们发生时尝试进行某种清理,但通常会重新抛出原始的Throwable

标签: java exception error-handling exception-handling runtime-error


【解决方案1】:

Exception e 参数未在您的 catch 块中使用,但它可用于显示有关已捕获异常的信息(异常消息、堆栈跟踪等...)。您可以决定在 catch 块中抛出一种新类型的异常,在这种情况下,您可以将 e 传递给新异常的构造函数。

例如:

catch(Exception e){
    e.printStackTrace ();
}

异常是类的实例,带有 X 类型异常的 catch 块可以捕获任何 X 类型或 X 子类的异常。因此catch(Exception e)catch (ArithmeticException arithmeticException) 都可以捕获@987654326 @。 (因为ArithmeticExceptionException 的间接子类)。

正如 Andy 评论的那样,您通常应该更喜欢捕获最具体的异常类型(在您的示例中为 ArithmeticException),以确保您只捕获您想要捕获的异常。例如,在您的代码中,catch (Exception e) 也会捕获其他异常 - NoSuchElementExceptionIllegalStateException 可能由 scanner.nextInt() 抛出。

【讨论】:

  • 我要补充一点:但是,您应该尽可能捕获最具体的异常,否则您可能会无意中无法处理随着代码的发展而添加到方法签名中的特定异常类型(例如 @987654334 @)。
【解决方案2】:

这是因为ArithmeticExceptionException 的子级。这是面向对象编程(OOP)的基本原则:https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

这基本上意味着ArithmeticException 也是一个Exception(嗯,它继承自它)。但是Exception 不一定是ArithmeticException,它也可以是IllegalArgumentExceptionException 的任何其他子代。

【讨论】:

    【解决方案3】:

    你总是catchException - 这是异常处理的本质,因此Java 语言需要catch 块来捕获Exception。通常,您会想做一些比仅在标准输出上打印“发生错误”更有用的事情,例如抛出您自己的异常或获取堆栈跟踪,在这种情况下您将使用e 对象。

    关于你的第二个问题,Exception 只是一个类,有很多子类,其中一个是ArithmeticException。因此,当您看到 ExceptionArithmeticException 在您的 catch 块中工作时,它只是在工作中的继承。

    【讨论】:

      【解决方案4】:

      回答你第二个问题。当scanner.nextInt() 试图解析不是数字的东西(例如one)时,ArithmeticException 被抛出。

      由于ArithmeticException 继承自Exception,因此两个catch 签名都有效以捕捉可能的ArithmenticExction。使用Exception 的catch 签名还会捕获其他错误,例如IOExceptionNullPointerException

      【讨论】:

        【解决方案5】:

        为什么它需要异常 e,因为它没有在任何地方使用?

        因为它应该被使用。该代码实际上忽略了有关错误的信息并打印出通用且无用的消息。异常包含有关所发生情况的信息,并且对于纠正问题至关重要。它至少应该记录在某个地方。

        这两种不同类型的错误如何处理同一个代码块?

        代码块中的各种操作可能会以各种方式失败。有时可能需要以与另一种不同的方式处理一种故障。例如,如果数据库交互失败,您可能希望记录错误并通知 DBA 并完全终止应用程序,但如果发生算术错误,那么您可能希望通知开发人员并返回默认值并允许应用程序继续.

        了解捕捉异常与处理异常有很大不同。如何处理异常(即系统如何在逻辑上响应错误条件)完全取决于应用程序的逻辑。有些错误是可以恢复的,有些则不能。有些暗示更重要的问题,有些则没有。通过拥有多个以不同方式响应不同类型错误的 catch 块,您可以有意义地处理这些不同的错误情况。

        【讨论】:

          【解决方案6】:

          你有两个问题,让我们按正确的顺序回答。

          现在我的问题是为什么它需要异常 e,因为它没有在任何地方使用?

          您基于糟糕的编码示例提出了这个问题,这个示例甚至没有记录异常类型,这使得它在现实生活中完全没用。 如果您只想记录您的异常,您应该至少记录错误消息。 另一件事是,您可能想要不同的行为,或者您希望在代码的不同位置处理不同的异常。因此异常类型可能非常有用。

          那么这两种不同类型的错误如何与同一个代码块一起工作 很简单,所有异常都是层次结构中的,在您的情况下,ArithmeticException 由 'nextInt' 方法引发扩展 Exception

          如果您想查看更多异常层次结构,请查看这张图片

          【讨论】:

            【解决方案7】:

            回答标题问题:

            您可以使用抛出的e 异常来帮助您诊断问题:

            try {
                ...
            } catch (Exception e) {
                System.out.println("Thrown exception: " + e.getMessage());
                //OR, for a custom error
                throw new Exception("Error in try block", e);
            }
            

            回答你的第二个问题:

            Java 中的所有异常都从基本的Exception 类型扩展而来,因此拥有catch(Exception e) 将捕获try 块内抛出的所有异常。

            您可以有多个 catch 块来处理不同的错误:

            try {
                ...
            } catch (ArithmeticException ae) {
                System.out.println("This was an arithmetic exception.");
            } catch (IOException ioe) {
                System.out.println("This was an I/O exception.");
            }
            

            但是一个通用的catch (Exception e) 不会给你任何有用的诊断数据,除非你使用抛出的e 异常:

            try {
                ...
            } catch (Exception e) {
                System.out.println("Thrown exception: " + e.getMessage());
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2020-05-18
              • 1970-01-01
              • 2017-06-19
              • 2021-05-13
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多