【问题标题】:How to handle multiple exceptions in a java method?如何处理java方法中的多个异常?
【发布时间】:2015-05-08 00:27:22
【问题描述】:

我已经阅读过这样处理多个异常不是最佳实践:

public void myMethod() throws ExceptionA, ExceptionB, ExceptionC {
    //more code here
}

然后调用myMethod():

try {
    myObject.myMethod();
} catch(Exception e) {
    //More code here
}

尽管 Exception 是所有其他异常的父类,但它被认为是一种不好的做法。但是,在我的应用程序中,我使用的是 java SE 6,我需要:

  • 执行可能暗示 FileNotFOundException 和 IOException 的文件操作
  • Marshal 对象(为了创建 XML 文件)JAXBException
  • 创建一个pdf文件(使用pdfbox库)COSVisitorException
  • 使用 JavaMail 发送电子邮件,MessagingException

最简单的方法是在方法声明中添加 throws 语句,但是编写客户端方法的正确方法是什么?

是否可以添加 6 个或 7 个 catch 块来处理所有可能的异常?

【问题讨论】:

  • 是的。多个 catch 块是要走的路。
  • @JarrodRoberson 为什么用 C# 问题结束 Java 问题?
  • 复制粘贴错误,用java重新关闭

标签: java exception


【解决方案1】:

一般来说(对于 Java 6 及以下版本),您应该单独处理每个异常...

try {
    myObject.myMethod();
} catch (ExceptionA e) {
    // Condition for A
} catch (ExceptionB e) {
    // Condition for B
} catch (ExceptionC e) {
    // Condition for C
}

这允许您根据每个异常的不同来处理每个异常,但也意味着您只处理那些报告为由方法抛出的异常

在 Java 7+ 中,您可以使用“multi-catch”或“combined catch”(我们找不到“官方”术语)

try {
    myObject.myMethod();
} catch (ExceptionA | ExceptionB | ExceptionC e) {
    // Condition for A and B and C
}

但即便如此,您也应该将例外集中在“常见”使用组中

try {
    myObject.myMethod();
} catch (ExceptionA | ExceptionB e) {
    // Condition for A and B
} catch (ExceptionC e) {
    // Condition for C
}

如果您控制异常的定义方式,另一种选择是从公共基础异常扩展,这方面的一个很好的例子是 FileNotFoundException,它从 IOException 扩展而来,FileReader 和FileInputStream(作为示例),这意味着您可以根据需要将FileNotFoundException 作为普通IOException 处理...

FileReader fr = null;
try {
    fr = new FileReader(new File(...));
    // Read from reader...
} catch (IOException exp) {
    // Common catch block
} finally {
    // Best attempt to close
    try {
        fr.close();
    } catch (Exception exp) {
    }
}

或者您可以根据自己的情况处理FileNotFoundException...

FileReader fr = null;
try {
    fr = new FileReader(new File(...));
    // Read from reader...
} catch (FileNotFoundException exp) {
    // File not found condition
} catch (IOException exp) {
    // Other IO condition
} finally {
    // Best attempt to close
    try {
        if (fr != null) {
            fr.close();
        }
    } catch (Exception exp) {
    }
}

这允许您将“喜欢”的异常组合在一起,但也可以让您在需要时定义更细粒度的条件...

但请注意,在上面的示例中,如果我将 IOException 放在首位,FileNotFoundException 将永远不会被处理,这样做时,请确保首先使用最低/最严格/最好的异常,因为它们是按照您列出的顺序依次处理

另一个选项(我不喜欢,但已经看到)可能是捕获一个“共同”祖先,然后比较实际类型,这将允许您为异常的某些子类型提供通用处理程序.

} catch (IOException exp) {
    if (exp instanceof FileNotFound || exp instanceof FileSystemException) {   
        // Common handling
    } else {
        // Generic handling
    }
}

这在方法只抛出祖先类型(即IOException)的情况下可能会有所帮助,但您需要提供更细粒度的分辨率

但是,我将再次专注于处理声明为已抛出的预期“常见”异常,例如,不要急于捕捉 Throwable

【讨论】:

  • 我以前从未听说过称为“多个 catch 块”的组合 catch 子句,我想说这个名称很容易与术语“多个 catch 块”混淆,意思是多个 catch 块。真的没有更好的名字吗?我一直都知道它是一个联合捕获块。在 cmets 中回复您后,我意识到这种命名差异。
  • 我通常将它们称为“multi-catch”,但称它们为“multiple-catch blocks”很可能会与“multiple-catch-blocks”混淆,是的。
  • @Raniz 我想说,连字符对于区分两者至关重要。 “多抓”我很清楚。
  • 那么,方法中处理的异常没有最大数量?而且,每个捕获条件下的 DRY 原则如何?
  • @MadProgrammer 似乎“multi-catch”是官方术语provided by Eclipse(虽然我还是很喜欢“combined catch”!)。还有一个multi-catch 标签。
猜你喜欢
  • 2015-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多