Java中try/catch块中的返回语句

3
假设我有以下内容:
class NegativeException extends RuntimeException {
}

class ZeroException extends NegativeException {
}

class Driver {
    static boolean Marathon(int a) {
        try {
            if (a < 0)
                throw new NegativeException();
            else if (a == 0)
                throw new ZeroException();
            else if (a >= 42)
                return true;
            else
                return false;
        } catch (ZeroException e) {
            System.out.println("Use natural number");
        } finally {
            System.out.println("One last thing");
        }
        System.out.println("All done.");
        return false;
    }

    public static void main(String[] args) {
        /* One last thing */
        /* true */
        System.out.println(Marathon(100));


        System.out.println(Marathon(0));
        System.out.println(Marathon(-5));

    }
}

我试图理解的是为什么当使用我们主方法的第一行"Marathon(100)"时,"All done"这行不会执行?
似乎finally语句会在return语句被输出之后才被执行。我知道无论发生什么情况,finally块都将始终执行。但是,我似乎无法理解return语句如何影响try-catch-finally块的流程。在尝试从try-catch-finally块返回时是否存在一些规则?

2
"类ZeroException扩展NegativeException" 嗯...记住,“扩展”意味着存在“是一个”的关系。“0是负数”是不正确的。 - T.J. Crowder
1个回答

6
我尝试理解的是,为什么当我们执行主方法的第一行时,“全部完成”这一行不会被执行? 这是因为“a>=42”成立,所以你会执行以下操作:
return true;

...这会立即将控制权转移到finally块;在finally块结束时,函数返回(不会运行finally块之后的任何行)。也就是说,return不仅设置了返回值,而且在运行所有未完成的finally块后,在该点终止函数。

如果希望继续执行,可以写入一个变量,然后在最后有一个单独的return

static boolean Marathon(int a) {
    boolean rv = false;
    try {
        if (a < 0)
            throw new NegativeException();
        else if (a == 0)
            throw new ZeroException();
        else if (a >= 42)
            rv = true;
    } catch (ZeroException e) {
        System.out.println("Use natural number");
    } finally {
        System.out.println("One last thing");
    }
    System.out.println("All done.");
    return rv;
}

returntrycatch中的更多信息:如果你在一个有finally块的try中使用return,它会立即转移到finally块。当到达该块的末尾时,函数将终止(不会运行任何finally块之后的代码,除非你有嵌套的finally块或类似情况)。如果你在catch中使用return,也会发生同样的事情。

例如:

try {
    if (someCondition) {
        return 1;
    }
    if (someOtherCondition) {
        throw new Exception();
    }
}
catch (Exception e) {
    System.out.println("Got here because of exception");
    return 2;
}
finally {
    System.out.println("Got here");
}
System.out.println("May not have gotten here");
return 3;

无论如何,"Got here"都会被输出;这就是finally语句块的作用,它们总是会被执行。
只有当someOtherCondition为真时(并且在"Got here"之前),"Got here because of exception"才会被输出,并以值1正常返回。
如果someConditionsomeOtherCondition为真,则"May not have gotten here"不会被输出,因为在trycatch块中已经有了return
如果两个条件都不为真,则你会看到"May not have gotten here"后面跟着"Got here",函数将返回3
请注意,在catch块中的return意味着当someOtherCondition为真时,函数将正常返回(值为2),而不是抛出异常。如果你没有在那里使用return,并且someOtherCondition为真,你将会看到"Got here because of exception""Got here",然后函数将终止并抛出异常(没有返回值),并且不会输出"May not have gotten here"
最后但并非最不重要的是:如果你在finally块中使用了一个return,那么这个return将会"胜出":即使你已经在函数中使用了returnfinally块中的return也会覆盖它,使函数返回finally指定的值,而不是之前的值。

1
@JBNizet: “Right: *"...它终止函数在此点(除finally子句和类似情况之外)"的意思是"除了finally子句和类似情况之外" --例如,它们被执行。我会重新措辞,也许"barring"并不清楚。” - T.J. Crowder
@T.J.Crowder 太好了!这刚刚澄清了一切!谢谢! - Dimitri
1
@Dimitri:很高兴能帮到你。我将那些东西整合到了答案中。 :-) - T.J. Crowder
1
@Dimitri:啊!抱歉,已修复——看,你现在是专家了! - T.J. Crowder
1
@T.J.Crowder 只是确保我把所有的事情都考虑到了! :) - Dimitri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接