在这段代码中,例外如何涓涓细流?

时间:2018-03-16 17:40:51

标签: java exception exception-handling

有一些第三方代码如下所示。假设有两个类,classA和classB,它们的定义是正确的,它们按预期工作。

// this function does not have a *throws Exception* in its definition
public Collection<classA> doSomething(String someStr) {

    List<ClassA> ClassAList = new ArrayList<ClassA>();
    int a = 0;

    while (a < 5) {
        classAList.add(
            new classA(
                someStr,
                new Callable<classB>() {
                    public classB call() throws Exception {
                        // do some work here
                        try {
                            // try something new
                        } catch (Exception e) { // <---- THIS EXCEPTION
                            // do something exceptional
                            throw e;
                        }
                        // do more work here, because why not?
                    }
                }
            )
        );
        a++;
    }
    return classAList;
}

这是一个人为的例子,所以它可能并不完全合情合理。但是,它准确地反映了我的代码。

我想弄清楚的是,如果抛出异常会发生什么?异常是否突破,整个 doSomething 函数失败了? (我怀疑是这种情况,但是上层函数没有“抛出异常”,所以可能是我错了?)

我对Java比较陌生,之前绝对没有见过这种编程风格(如果你知道它叫什么,所以我可以更多地研究它,请让我知道) - 我有一个C背景和Python,所以-__(oO)__ / -

注意:这是对某些内容的扩展,因此无法直接运行以进行调试。

注2 :此问题被标记为this的可能副本。我不是在没有异常抛出子句的情况下询问这是如何编译的。我试图找出抛出异常的位置/时间。

3 个答案:

答案 0 :(得分:2)

我认为此处的Callable类型为java.util.concurrent.Callable

实际上永远不会在doSomething的堆栈帧上抛出异常。这是因为它是在一个实现Callable<classB>的匿名内部类中定义的。它根本不在doSomething中调用。然后将匿名类的实例传递到classA的构造函数中,创建classA的新实例并将其放入列表中。这解释了为什么doSomething不需要throws

现在,如果您要访问该列表,请从Callable<classB>的实例获取classA,然后致电Callable.call()需要处理通过在周围方法中添加``try ... catch or adding a throws`子句来检查异常,如下所示:

public void doSomethingElse() throws Exception{
    ClassAList.get(0).getCallable().call(); // exception might be thrown here!
}

答案 1 :(得分:1)

这不可能发生,因为Exception是一个经过检查的例外。您的方法签名中没有throws子句。我的猜测是编译器会抱怨你的示例代码。

您必须将其切换为未选中的RuntimeException,或将throws子句添加到方法签名中。

即使你这样做,我也会说这是一个糟糕的设计。

捕获异常表明您可以做一些明智的事情来从中恢复。它可能几乎没有任何东西可以记录这个事实,或者像清理资源和优雅地结束任务那样更重要的事情。

但抓住和重新投掷对我来说似乎是一种浪费。我宁愿添加throws子句而不是捕获异常,所以有人可以做一些明智的事情来从问题中恢复。

答案 2 :(得分:1)

您提供的代码只是定义Callable's。它不会在doSomething方法中执行,因此它不会在那里抛出异常。在实际执行Callable(通过call()或将其提交给ExecutorService)的地方可以抛出异常。

查看此示例https://www.journaldev.com/1090/java-callable-future-example