Java:使用RuntimeException从访问者中逃脱

Chr*_*way 10 java callcc exception visitor

我很有诱惑力使用未经检查的异常作为Java程序中的短路控制流构造.我希望有人能以更好,更清洁的方式告诉我这个问题.

我的想法是,我希望减少访问者对子树的递归探索,而不必在每个方法调用中检查"停止"标志.具体来说,我正在使用抽象语法树上的访问者构建控制流图.returnAST中的语句应该停止对子树的探索,并将访问者发送回最近的封闭if/then或循环块.

Visitor超类(从XTC库)定义

Object dispatch(Node n)
Run Code Online (Sandbox Code Playgroud)

通过表单的反射方法回调

Object visitNodeSubtype(Node n)
Run Code Online (Sandbox Code Playgroud)

dispatch 没有声明抛出任何异常,所以我声明了一个扩展的私有类 RuntimeException

private static class ReturnException extends RuntimeException {
}
Run Code Online (Sandbox Code Playgroud)

现在,return语句的visitor方法看起来像

Object visitReturnStatement(Node n) {
    // handle return value assignment...
    // add flow edge to exit node...
    throw new ReturnException();
}
Run Code Online (Sandbox Code Playgroud)

并且每个复合语句都需要处理 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 ) { }
}
Run Code Online (Sandbox Code Playgroud)

这一切都很好,除了:

  1. 我可能忘了赶上ReturnException某处,编译器不会警告我.
  2. 我觉得很脏

有一个更好的方法吗?有没有Java模式我不知道实现这种非本地控制流?

[更新]这个具体的例子有点无效:Visitor超类捕获并包装异常(甚至是RuntimeExceptions),因此异常抛出并没有真正帮助.我已经实现了从中返回enum类型的建议visitReturnStatement.幸运的是,这只需要在少数几个地方进行检查(例如visitCompoundStatement),所以实际上比抛出异常要麻烦一点.

总的来说,我认为这仍然是一个有效的问题.虽然也许,如果你不依赖第三方库,可以通过合理的设计避免整个问题.

Eli*_*lie 0

您不只是返回一个值有什么原因吗?比如NULL,如果你真的想什么也不返回?这会简单得多,并且不会冒抛出未经检查的运行时异常的风险。