Java 为什么;捕获;块是否需要异常类型?

Java 为什么;捕获;块是否需要异常类型?,java,exception,error-handling,exception-handling,runtime-error,Java,Exception,Error Handling,Exception Handling,Runtime Error,在java中的异常处理方面,我已经看到所有的try-catch块都需要一种它必须处理的异常类型,更常见的是: catch(Exception e){ System.out.println("Error occured"); } 现在我的问题是,为什么它需要异常e,因为它没有在任何地方使用? 我的第二个问题关于我刚刚编写的以下代码: Scanner scanner = new Scanner(System.in); int x = 1; do { try {

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

 catch(Exception e){
 System.out.println("Error occured");
}
现在我的问题是,为什么它需要
异常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(arithmetricexception arithmetricexception)和catch(Exception e)那么这两种不同类型的错误如何处理同一代码块呢?

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

例如:

catch(Exception e){
    e.printStackTrace ();
}
异常是类的实例,具有类型X异常的catch块可以捕获类型X或子类X的任何异常。因此
catch(异常e)
catch(算术异常算术异常)
都可以捕获
算术异常。(因为
算术异常
异常
的间接子类)


正如Andy所评论的,您通常应该更喜欢捕获最具体的异常类型(
arithmetricexception
,在您的示例中),以确保只捕获您想要捕获的异常。例如,在您的代码中,catch(Exception e)
也将捕获其他异常-
NoSuchElementException
IllegalStateException
,这可能是由
scanner.nextInt()

引发的,因为
算术异常
异常
的子项。这是面向对象编程(OOP)的基本原则:


它基本上意味着
算术异常
也是一个
异常
(好吧,它继承自它)。但是
异常
不一定是
算术异常
,它也可能是
非法argumentexception
异常
的任何其他子项

您总是
捕获
异常
-这是异常处理的本质,因此,java语言需要一个
catch
块来捕获
异常。通常,您希望做一些比仅在标准输出上打印“出错”更有用的事情,比如抛出您自己的异常或获取stacktrace,在这种情况下,您将使用
e
对象


关于第二个问题,
Exception
只是一个类,有很多子类,其中一个是
arithmetricexception
。因此,当您在catch块中看到
异常
算术异常
都在工作时,这只是工作中的继承。

回答第二个问题<代码>算术异常
scanner.nextInt()
在尝试解析非数字的内容(如
one
时引发

由于
算术异常
继承自
异常
,因此两个catch签名对于捕获可能的
算术执行
都是有效的。使用
Exception
的catch签名还将捕获其他错误,例如
IOException
NullPointerException

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

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

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

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


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

您有两个问题,让我们按照正确的顺序回答它们

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

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

那么这两种不同类型的错误如何在同一代码块中工作 很简单,所有异常都是按层次结构组织的,在您的例子中,'nextInt'方法引发的
算术异常
扩展了
异常

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

try {
    ...
} catch (Exception e) {
    System.out.println("Thrown exception: " + e.getMessage());
    //OR, for a custom error
    throw new Exception("Error in try block", e);
}
try {
    ...
} catch (ArithmeticException ae) {
    System.out.println("This was an arithmetic exception.");
} catch (IOException ioe) {
    System.out.println("This was an I/O exception.");
}
try {
    ...
} catch (Exception e) {
    System.out.println("Thrown exception: " + e.getMessage());
}