在此代码中,异常是如何产生的?
How do exceptions trickle up, in this code?
有一些第三方代码如下所示。假设有两个 类,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函数失效? (我怀疑是这种情况,但上层函数没有 "throws Exception",所以我可能错了吗?)
我对Java比较陌生,以前肯定没见过这种编程风格(另外,如果你知道它叫什么,我可以进一步研究它,请告诉我)-我有 C 和 Python 的背景,所以 -__(o.O)__/-
注意:这是对某物的扩展,因此不能运行直接调试。
注释 2:此问题被标记为可能与 this 重复。我不是在问如何在没有异常抛出子句的情况下进行编译。我正在尝试找出 where/when 抛出的异常。
这不可能发生,因为 Exception
是一个已检查的异常。您的方法签名中没有 throws 子句。我的猜测是编译器会抱怨您的示例代码。
您必须将其切换为未选中的 RuntimeException
,或者将 throws 子句添加到您的方法签名中。
即使你这样做,我也会说这是一个糟糕的设计。
捕获异常表明您可以做一些明智的事情来从中恢复。它可能几乎没有记录事实,或者更重要的事情,比如清理资源和优雅地结束任务。
但是捕捉和 re-throwing 对我来说似乎是一种浪费。我宁愿添加 throws 子句而不是捕获异常,以便在线的人可以做一些明智的事情来从问题中恢复。
您提供的代码只是定义 Callable's
。它不会在 doSomething
方法中执行,因此不会在那里抛出异常。在实际执行 Callable
的地方可能会抛出异常(通过 call() 或将其提交给 ExecutorService)。
看看这个例子https://www.journaldev.com/1090/java-callable-future-example
我假设这里的 Callable
类型是 java.util.concurrent.Callable
.
异常实际上永远不会在doSomething
的堆栈帧上抛出。这是因为它是在实现 Callable<classB>
的匿名内部 class 中定义的。它根本没有在 doSomething
中调用。然后将匿名 class 的实例传递给 classA
的构造函数,创建 classA
的新实例并将其放入列表中。这就解释了为什么 doSomething
不需要 throws
现在,如果您要访问列表,从 classA
的实例中获取 Callable<classB>
,然后调用 Callable.call()
,您 do 需要通过在周围方法中添加 ``try...catchor adding a
throws` 子句来处理已检查的异常,如下所示:
public void doSomethingElse() throws Exception{
ClassAList.get(0).getCallable().call(); // exception might be thrown here!
}
有一些第三方代码如下所示。假设有两个 类,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函数失效? (我怀疑是这种情况,但上层函数没有 "throws Exception",所以我可能错了吗?)
我对Java比较陌生,以前肯定没见过这种编程风格(另外,如果你知道它叫什么,我可以进一步研究它,请告诉我)-我有 C 和 Python 的背景,所以 -__(o.O)__/-
注意:这是对某物的扩展,因此不能运行直接调试。
注释 2:此问题被标记为可能与 this 重复。我不是在问如何在没有异常抛出子句的情况下进行编译。我正在尝试找出 where/when 抛出的异常。
这不可能发生,因为 Exception
是一个已检查的异常。您的方法签名中没有 throws 子句。我的猜测是编译器会抱怨您的示例代码。
您必须将其切换为未选中的 RuntimeException
,或者将 throws 子句添加到您的方法签名中。
即使你这样做,我也会说这是一个糟糕的设计。
捕获异常表明您可以做一些明智的事情来从中恢复。它可能几乎没有记录事实,或者更重要的事情,比如清理资源和优雅地结束任务。
但是捕捉和 re-throwing 对我来说似乎是一种浪费。我宁愿添加 throws 子句而不是捕获异常,以便在线的人可以做一些明智的事情来从问题中恢复。
您提供的代码只是定义 Callable's
。它不会在 doSomething
方法中执行,因此不会在那里抛出异常。在实际执行 Callable
的地方可能会抛出异常(通过 call() 或将其提交给 ExecutorService)。
看看这个例子https://www.journaldev.com/1090/java-callable-future-example
我假设这里的 Callable
类型是 java.util.concurrent.Callable
.
异常实际上永远不会在doSomething
的堆栈帧上抛出。这是因为它是在实现 Callable<classB>
的匿名内部 class 中定义的。它根本没有在 doSomething
中调用。然后将匿名 class 的实例传递给 classA
的构造函数,创建 classA
的新实例并将其放入列表中。这就解释了为什么 doSomething
不需要 throws
现在,如果您要访问列表,从 classA
的实例中获取 Callable<classB>
,然后调用 Callable.call()
,您 do 需要通过在周围方法中添加 ``try...catchor adding a
throws` 子句来处理已检查的异常,如下所示:
public void doSomethingElse() throws Exception{
ClassAList.get(0).getCallable().call(); // exception might be thrown here!
}