这个想法是,我想缩短访问者对子树的递归检索,而无需在每个方法调用中检查“停止”标志.具体来说,我正在使用访问者在抽象语法树上构建一个控制流图. AST中的返回语句应该停止对子树的查找,并将访问者发送回最接近的if / then或循环块.
访客超类(从XTC library)定义
Object dispatch(Node n)
它通过形式的反射方法回调
Object visitNodeSubtype(Node n)
dispatch没有声明抛出任何异常,所以我宣布一个扩展RuntimeException的私有类
private static class ReturnException extends RuntimeException { }
现在,返回语句的访问者方法看起来像
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模式,我不知道实现这种非本地流控制?
[UPDATE]这个具体的例子证明是有点无效的:Visitor超类捕获和包装异常(甚至是RuntimeExceptions),所以异常抛出并没有真正的帮助.我已经实现了从visitReturnStatement返回枚举类型的建议.幸运的是,这只需要在少量的地方进行检查(例如visitCompoundStatement),所以实际上比抛出异常更麻烦一些.
一般来说,我认为这仍然是一个有效的问题.虽然也许,如果你没有绑定到第三方图书馆,整个问题可以通过合理的设计来避免.
解决方法
>您正在使用第三方,无法添加已检查的异常
>在一大群访客中检查返回值是唯一必要的,这是一个不必要的负担
此外,还有那些人认为是unchecked exceptions aren’t all that bad.您的使用提醒了我的Eclipse的OperationCanceledException,它用于吹出长时间运行的后台任务.
这不是完美的,但如果有文件记录,似乎对我来说很好.