【问题标题】:Why is catch block optional?为什么 catch 块是可选的?
【发布时间】:2015-05-05 14:07:18
【问题描述】:

我有以下代码

public static void nocatch()
{
    try
    {
        throw new Exception();
    }
    finally
    {

    }
}

这给出了错误

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
Unhandled exception type CustomException

我的问题是,当没有 catch 无法绕过时,为什么将 catch 块设计为可选?


从 finally() 的角度来看,我理解

finally 应该至少有一个 try 块,catch 是可选的。 finally 块的目的是确保无论是否引发异常,都可以清理内容。根据JLS

finally 子句确保 finally 块在 try 块和任何可能执行的 catch 块之后执行,无论控制如何离开 try 块或 catch 块。


编辑:

通过在 finally 块中添加返回,编译器不会给出错误 WHY?!

public static void nocatch()
{
    try
    {
        throw new Exception();
    }
    finally
    {
        return; //By adding this statement, the compiler error goes away! Please let me know why
    }
}

【问题讨论】:

  • 关于“为什么”的问题几乎是基于意见的;事实上,Java 是(据我所知)唯一具有检查异常概念的语言,而且您的 CustomException 似乎就是这样一个异常。并且有处理已检查异常的规则。
  • 它允许您实现finally 子句。它不会“隐藏”异常。
  • 将在此处尝试使用资源 (docs.oracle.com/javase/tutorial/essential/exceptions/…) 以省略 finally ;)
  • CustomException 是什么无关紧要。为了争论,我们只考虑Exception
  • @HotLicks:“责备”当然是指“对 Java 语言和环境的一项突出特性给予应有的尊重和尊重”。 ;-)

标签: java exception exception-handling try-catch try-catch-finally


【解决方案1】:

我的问题是,为什么在没有 catch 的情况下无法绕过 catch 块?

是的有:声明方法抛出异常:

public static void nocatch() throws CustomException
{
    try
    {
        throw new CustomException();
    }
    finally
    {

    }
}

try/finally 没有catch 是为了确保您清理任何需要清理的东西,即使您自己没有处理异常。 (确保不允许从finally 中引发任何其他异常,否则您将隐藏主要异常。)

这是一个可以使用的示例 (live copy):

private static class CustomException extends Exception {
}
public static void main (String[] args) throws java.lang.Exception
{
    try
    {
        System.out.println("Calling nocatch(false)");
        nocatch(false);
    }
    catch (CustomException ce) {
        System.out.println("Caught CustomException for false case");
    }
    try
    {
        System.out.println("Calling nocatch(true)");
        nocatch(true);
    }
    catch (CustomException ce) {
        System.out.println("Caught CustomException for true case");
    }
}

public static void nocatch(boolean foo) throws CustomException
{
    try
    {
        if (foo) {
            System.out.println("Throwing");
            throw new CustomException();
        }
    }
    finally
    {
        System.out.println("In finally");
    }
    System.out.println("Reached outside the try/finally block");
}

输出:

调用 nocatch(false) 终于在 到达 try/finally 块之外 调用 nocatch(true) 投掷 终于在 为真实情况捕获 CustomException

如您所见,无论是否发生异常,finally 块的代码都会运行,但try/finally 之后的代码不会。


您的后续跟进询问为什么在 finally 中添加 return 会使错误消失:

try
{
    throw new CustomException();
}
finally
{
    return; // <=== Makes the compiler happy (but don't do it!)
}

有趣的边缘案例!这是因为finally 块中的代码总是运行,所以你总是返回而不是抛出,隐藏了发生的异常。例如,这是序列:

  1. throw new CustomException() 抛出异常,将控制权转移到 finally 块

  2. finally 块中的代码从方法发出正常返回

这隐藏了异常发生的事实;实际上,您已经通过 finally 块“处理”了异常(没有实际处理它)。一般来说,这不是一个好主意。使用catch处理异常,或者在方法上声明它们以便调用代码可以处理它们。

【讨论】:

  • 如果您有 throws 子句,则首先不需要 try{}。但如果我理解正确,在上述情况下,我们添加 try 块只是为了让 finally... 对吗?
  • @codeMan: Right: 目的是说“我要做这个东西,这可能会抛出异常;不管它是否发生,一定要运行我的finally 代码所以以后我可以收拾了。”这就是为什么标准 try 必须 后跟 catch 或 finally(或两者)(try-with-resources 可以完全独立,因为它具有 implicit catch 和 finally 子句)。
  • 感谢您提供额外信息。还有一件事我无法理解。我已经编辑了我的问题,请你看一下。
  • @codeMan:在底部添加一点:这是因为如果你这样做,你的方法将不再抛出。
猜你喜欢
  • 2014-10-19
  • 1970-01-01
  • 2011-03-07
  • 1970-01-01
  • 2019-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-25
相关资源
最近更新 更多