Java 使用Exception类或FileNotFoundException类捕获异常之间的区别

Java 使用Exception类或FileNotFoundException类捕获异常之间的区别,java,exception,Java,Exception,就像我有两个场景,我们必须处理FileNotFoundException 案例1: try { FileInputStream fis = new FileInputStream("test1.txt"); } catch (FileNotFoundException e) { e.printStackTrace(); } 案例2: try { FileInputStream fis = new FileInpu

就像我有两个场景,我们必须处理FileNotFoundException

案例1:

    try {
        FileInputStream fis = new FileInputStream("test1.txt");
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } 
案例2:

    try {
        FileInputStream fis = new FileInputStream("test1.txt");
    } catch (Exception e) {
        e.printStackTrace();
    }
在这两种情况下,打印的堆栈跟踪是相同的。我想知道这两种实现之间的区别以及应该首选什么?

从中可以看出,它给出了原因:

子类继承所有成员(字段、方法和嵌套 构造函数不是成员,因此 不是由子类继承的,而是由超类的构造函数继承的 可以从子类调用。”


异常类是所有其他异常类的父类。因此,如果您知道将获得
FileNotFoundException
,那么最好使用该异常。生成
异常
是一个通用调用

这将帮助您了解:

正如您所看到的,Exception类位于更高的层次结构中,这意味着它将捕获除FileIOException之外的任何异常。但是,如果要确保打开由指定路径名表示的文件的尝试失败,则必须使用FileIOExction

因此,理想的方法应该是:

try {
      // Lets say you want to open a file from its file name.
    } catch (FileNotFoundException e) {
      // here you can indicate that the user specified a file which doesn't exist.
      // May be you can try to reopen file selection dialog box.
    } catch (IOException e) {
      // Here you can indicate that the file cannot be opened.
    }
而相应的:

try {
  // Lets say you want to open a file from its file name.
} catch (Exception e) {
  // indicate that something was wrong
  // display the exception's "reason" string.
}

也要检查这一点:

这是你想要拦截什么的问题。使用
Exception
您将捕获任何异常,但使用
FileNotFoundException
您将只捕获该错误情况,从而允许调用方捕获并应用任何处理。

不要使用这些处理

不要捕捉异常。为什么?因为它还捕获所有未检查的异常(即,
RuntimeException
s和派生)。这些应该被收回

。为什么?因为它的异常是不可靠的(
FileNotFoundException
,例如,如果您尝试打开一个您没有读取权限的文件,可能会抛出该异常)

使用以下命令:

final Path path = Paths.get("test1.txt");
try (
    final InputStream in = Files.newInputStream(path);
) {
    // do something with "in"
} catch (FileSystemException e) {
    // fs level error: no permissions, is a directory etc
} catch (IOException e) {
    // I/O error
}

您确实需要在
IOException
之前捕获
FileSystemException
,因为前者是后者的子类。在其他可能的异常中,您可以有:
AccessDeniedException
FileSystemLoopException
NoSuchFileException
等。在案例2中,捕获的所有
异常
都将运行catch块,而不管它们是什么异常。这允许以相同的方式处理所有异常,例如为所有类型的异常显示相同的消息


在案例1中,
catch
块将仅针对
FileNotFoundException
s运行。在不同的
catch
块中捕获特定异常允许以不同的方式处理不同的异常,例如向用户显示不同的消息。

异常类是FileNotFoundException的父类


如果您在catch语句中提供了异常,那么每个异常都将在catch块中处理。但是,如果catch块中存在FileNotFoundException,则只会处理由于上述源中缺少文件或无法读取该文件的权限或导致破坏Java读取该文件的努力的任何此类问题而引发的异常。所有其他异常都将转义并向上移动堆栈

在您提供的代码片段中,两者都可以使用。但我建议使用FileNotFoundException,因为它指出了代码中的确切问题

有关更多详细信息,请在编写以下内容时阅读:

  try {
        FileInputStream fis = new FileInputStream("test1.txt");
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } 
只有当异常(在try块内引发)的类型为
FileNotFoundException
(或子类型)时,才会执行catch块内的代码。 另一方面,当你写这篇文章时:

try {
        FileInputStream fis = new FileInputStream("test1.txt");
    } catch (Exception e) {
        e.printStackTrace();
    }
catch块针对任何异常执行(因为
exception
是任何异常的根类型)

如果您的文件(test1.txt)不存在,将抛出FileNotFoundException,并且两个代码段都能够捕获它。 尝试将其更改为以下内容:

    try {
            FileInputStream fis = new FileInputStream("test1.txt");
        } catch (NullPointerException e) {
            e.printStackTrace();
        }

您将看到catch块不再执行。

当发生异常时,JVM抛出异常的实例,并将该实例传递给相应的catch块,因此在
catch(异常e)
中,e只是引用变量,但它指向的实例是异常抛出的实例

catch(FileNotFoundException e)
的情况下,e也是一个引用变量,它指向的实例是抛出的异常,因此在这两种情况下,不同的引用变量(即e)指向相同异常(抛出的)的实例

这是我喜欢的:

    try {
        // some task
    } catch (Exception e) {
        if (e instanceof FileNotFoundException) {

            // do this
        }
        if (e instanceof NullPointerException) {
            // do this
        } else {
            // do this
        }
    }

哇!四个答案中没有一个提到继承,也没有一个解释为什么或如何两个案例给出相同的结果;出于我在回答中提到的原因:捕获
异常
也意味着捕获所有未检查的异常,这对imho来说不是一件好事。“只有由于上述源缺少文件而出现的异常才会被处理”这是对的@fge。谢谢你指出这一点。我已经编辑了我的答案。