为什么 catch 块是可选的?

Why is catch block optional?

我有以下代码

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

    }
}

这给出了错误

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

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


从finally()的角度,我理解

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

A finally clause ensures that the finally block is executed after the try block and any catch block that might be executed, no matter how control leaves the try block or catch block.


编辑:

通过在 finally 块中添加一个 return,编译器不会给出错误 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
    }
}

My Question is why was it designed that the catch block is optional, when there is no way of getting around not having a catch?

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

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

    }
}

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

这里有一个例子可以玩 (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");
}

输出:

Calling nocatch(false)
In finally
Reached outside the try/finally block
Calling nocatch(true)
Throwing
In finally
Caught CustomException for true case

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


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

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

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

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

  2. finally 块中的代码从方法

  3. 发出正常的 return

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