锁定老帖子 主题:有关异常使用的一点疑惑
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2005-01-16
但是, 仍然有一个问题困扰着我. 比如说, 我有一个compile函数, Code compile(Func f); 它负责编译一个函数, 返回一个中间代码. compile函数内部, 会调用compileParameter()函数. 这个compileParameter内部会抛出一些不同的异常,比如"illegal type", "wrong name", "duplicate name" 等等. 但是, 这里, 我仍然被迫做try-catch-rethrow. 这是因为我需要在异常中加入额外的函数名字, 以及其它编译上下文信息来达到错误信息的准确定位. 我可以把这些信息都传递进compileParameter, 但是这样就造成了compileParameter和compile函数的更强的耦合, compileParameter函数本来没有必要知道这些的. 各位如何解决这类问题呢? 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2005-01-16
这个问题以前我一直很关关注。
现在对于异常的捕捉,一般也是基于checkedException的观点, 如果需要明确捕捉的则需要CheckedException,一般将它直接继承自Exception 或者 NestedException,这些需要显示声明要捕捉的。 另外如果要以异常捕捉作为流程流转的一部分的话,要十分注意未捕获的runtimeException,必要的话可以用 try.. catch(Exception e)来精确控制程序流程。(很多人反对) 如果一个方法抛出太多异常,也是值得考虑减少异常种类或者用一个中间层异常来封装。 至于你说的要精确定位错误点,我觉得如果要用异常来实现会造成异常类设计比较庞大,你不入仿造Log4j的办法,在每个类哪里注册一个错误捕捉类,在每一个编译的需要捕捉的异常处或者检查点,将这个错误的详细信息注册到你的捕捉类,外部接口可以查看错误捕捉类的详细信息。另外,你还可以在这个编译错误捕捉类那里格式化输出错误信息,比如xml阿或者你想要的咚咚。 |
|
返回顶楼 | |
发表时间:2005-01-16
如果偶没有理解错误的话,你是在问如何嵌套异常?
1.4的话用: new RuntimeException(String message, Throwable cause) 或者 new RuntimeException(Throwable cause) 1.3的话自己做一个Runtime的NestedException。 |
|
返回顶楼 | |
发表时间:2005-01-23
引用 这是因为我需要在异常中加入额外的函数名字, 以及其它编译上下文信息来达到错误信息的准确定位.
不知道你说的“错误信息的准确定位”具体是个什么定义。如果你只是指日志的话,exception stack trace足以定位错误发生源,你无需在异常中加入额外的函数名字。 谈到使用RuntimeException,我也很推崇这样的观点。最近做了一个用到Reflection的组件,其中有类似这样的方法:Object invoke(String methodName)。虽然这个组件是动态的,但在使用它的场景中,调用这个方法的程序员预先知道底层被invoke的那个object究竟有没有${methodName}这个方法。因此,这个组件抛出一个AccessFailureException extends RuntimeException,上层方法不必累赘地声明捕获或者重新throw;因为这样的Exception根本就不应该发生(发生的话,说明你code写得不对),所以一旦发生,程序应该立即fail掉。 何时使用RuntimeException?我斗胆得出个结论:当你想在编译期保证某些编译器检查不出来的错误不会发生,你反而应该使用RuntimeException。 |
|
返回顶楼 | |
发表时间:2005-01-23
我认为Checked Exception是java的一个失败的feature,它几乎就是一种另类的流程控制,且编程不友好(动不动要catch一堆东西,想想你用jdbc时的情景)。而且,我们绝大部分情况下用的是finally来做智源清理,异常只是用来在“异常”时打断当前执行栈,而不是直接抓住它来作处理(有点象COM的HRESULT了)。
|
|
返回顶楼 | |
发表时间:2005-04-08
towjzhou 写道 我认为Checked Exception是java的一个失败的feature,它几乎就是一种另类的流程控制,且编程不友好(动不动要catch一堆东西,想想你用jdbc时的情景)。而且,我们绝大部分情况下用的是finally来做智源清理,异常只是用来在“异常”时打断当前执行栈,而不是直接抓住它来作处理(有点象COM的HRESULT了)。
呵呵,是的。异常根本不该跟方法签名搅到一块,否则异常会象病毒一样在代码中传染。 |
|
返回顶楼 | |
发表时间:2005-04-09
引用 不知道你说的“错误信息的准确定位”具体是个什么定义。如果你只是指日志的话,exception stack trace足以定位错误发生源,你无需在异常中加入额外的函数名字。
这么说吧。 假设我编译的目标源代码如下: f(a, b, b); = a+b; 明显两个参数重名了。 照你的做法,出来得stack trace是这样: CompilationException: compileParameter line 3 > compileFunction line 5 > compileProgram line 7> 它告诉了我我的编译程序的哪个函数出错,但是并不能告诉我是被编译得那个目标源代码的哪一行,哪一个函数,哪一个参数错了。 我希望是这样: source file "test.jsl" function "f" 3rd parameter "b", name duplication. 这种trace是我必须自己维护的。 |
|
返回顶楼 | |
发表时间:2005-04-09
ajoo 写道 但是, 这里, 我仍然被迫做try-catch-rethrow. 这是因为我需要在异常中加入额外的函数名字, 以及其它编译上下文信息来达到错误信息的准确定位. 可以这么想,有三个错误类,CompileParameterException,CompilationFunctionException,CompilationException. 在compileFunction,捕获 CompileParameterException包装成CompilationFunctionException抛出,在compileProgram捕捉再包装成CompilationException.这样看着try-catch-rethrow就合理了,只不过觉得没有必要复杂,把这三个错误类简化成一个类了,但try-catch-rethrow还是保留了. 我会更倾向于让CompileParameter和compile更强耦合. |
|
返回顶楼 | |
发表时间:2005-04-09
要在stack trace中在每一级加入额外信息,恐怕除了这样做别无他法:
compileParameter(); { throw new CompilationException("duplicate parameter");; compileFunc(); { try { compileParameter();; } catch(CompilationException e); { e.addTracedMessage("In function XX");; throw e; } } 你就死心吧。 但我认为让compileFunc和compileParameter耦合的解决方案很不好。想想看:compileParameter需要compileFunc的信息所以与其耦合,那么同理,compileFunc也需要compileProgram的信息...如此一级级传递,层级上的所有元素都会双向耦合。 |
|
返回顶楼 | |
发表时间:2005-04-09
是啊。我同意你对耦合的·看法。看来,重复的rethrow是唯一办法了。
|
|
返回顶楼 | |