【发布时间】:2025-11-25 05:55:01
【问题描述】:
我非常想在 Java 程序中使用未经检查的异常作为短路控制流构造。我希望这里有人可以建议我以更好、更清洁的方式来处理这个问题。
我的想法是我想缩短访问者对子树的递归探索,而不必在每个方法调用中检查“停止”标志。具体来说,我正在使用抽象语法树上的访问者构建控制流图。 AST 中的return 语句应该停止探索子树并将访问者发送回最近的封闭 if/then 或循环块。
Visitor 超类(来自XTC library)定义
Object dispatch(Node n)
通过表单的反射方法回调
Object visitNodeSubtype(Node n)
dispatch 没有声明抛出任何异常,所以我声明了一个继承 RuntimeException 的私有类
private static class ReturnException extends RuntimeException {
}
现在,return 语句的访问者方法看起来像
Object visitReturnStatement(Node n) {
// handle return value assignment...
// add flow edge to exit node...
throw new ReturnException();
}
每个复合语句都需要处理ReturnException
Object visitIfElseStatement(Node n) {
Node test = n.getChild(0);
Node ifPart = n.getChild(1);
Node elsePart = n.getChild(2);
// add flow edges to if/else...
try{ dispatch(ifPart); } catch( ReturnException e ) { }
try{ dispatch(elsePart); } catch( ReturnException e ) { }
}
这一切都很好,除了:
- 我可能忘记在某处捕捉
ReturnException,编译器不会警告我。 - 我觉得很脏。
有没有更好的方法来做到这一点?是否有我不知道的 Java 模式来实现这种非本地控制流?
[更新] 这个具体的例子有些无效:Visitor 超类捕获并包装异常(甚至是RuntimeExceptions),所以抛出异常并没有真正的帮助。我已经实施了从visitReturnStatement 返回enum 类型的建议。幸运的是,这只需要在少数地方进行检查(例如,visitCompoundStatement),因此它实际上比抛出异常要少一些麻烦。
总的来说,我认为这仍然是一个有效的问题。虽然也许,如果您不依赖第三方库,则可以通过明智的设计避免整个问题。
【问题讨论】:
-
你的第 2 点让我笑了。这家伙的直觉很好......
标签: java exception visitor-pattern callcc