论坛首页 Java企业应用论坛

有关异常使用的一点疑惑

浏览 8452 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2005-01-16  
我现在也逐渐倾向使用runtime exception.主要是考虑到不要给架构带来影响,不强迫引入太多exception wrapping.

但是, 仍然有一个问题困扰着我.

比如说, 我有一个compile函数,

Code compile(Func f);


它负责编译一个函数, 返回一个中间代码.

compile函数内部, 会调用compileParameter()函数.


这个compileParameter内部会抛出一些不同的异常,比如"illegal type", "wrong name", "duplicate name"
等等.

但是, 这里, 我仍然被迫做try-catch-rethrow.
这是因为我需要在异常中加入额外的函数名字, 以及其它编译上下文信息来达到错误信息的准确定位.

我可以把这些信息都传递进compileParameter, 但是这样就造成了compileParameter和compile函数的更强的耦合, compileParameter函数本来没有必要知道这些的.

各位如何解决这类问题呢?
   发表时间:2005-01-16  
这个问题以前我一直很关关注。
现在对于异常的捕捉,一般也是基于checkedException的观点,
如果需要明确捕捉的则需要CheckedException,一般将它直接继承自Exception 或者 NestedException,这些需要显示声明要捕捉的。

另外如果要以异常捕捉作为流程流转的一部分的话,要十分注意未捕获的runtimeException,必要的话可以用 try.. catch(Exception e)来精确控制程序流程。(很多人反对)

如果一个方法抛出太多异常,也是值得考虑减少异常种类或者用一个中间层异常来封装。

至于你说的要精确定位错误点,我觉得如果要用异常来实现会造成异常类设计比较庞大,你不入仿造Log4j的办法,在每个类哪里注册一个错误捕捉类,在每一个编译的需要捕捉的异常处或者检查点,将这个错误的详细信息注册到你的捕捉类,外部接口可以查看错误捕捉类的详细信息。另外,你还可以在这个编译错误捕捉类那里格式化输出错误信息,比如xml阿或者你想要的咚咚。
0 请登录后投票
   发表时间:2005-01-16  
如果偶没有理解错误的话,你是在问如何嵌套异常?

1.4的话用:
new RuntimeException(String message, Throwable cause)
或者
new RuntimeException(Throwable cause)

1.3的话自己做一个Runtime的NestedException。
0 请登录后投票
   发表时间:2005-01-23  
引用
这是因为我需要在异常中加入额外的函数名字, 以及其它编译上下文信息来达到错误信息的准确定位.


不知道你说的“错误信息的准确定位”具体是个什么定义。如果你只是指日志的话,exception stack trace足以定位错误发生源,你无需在异常中加入额外的函数名字。



谈到使用RuntimeException,我也很推崇这样的观点。最近做了一个用到Reflection的组件,其中有类似这样的方法:Object invoke(String methodName)。虽然这个组件是动态的,但在使用它的场景中,调用这个方法的程序员预先知道底层被invoke的那个object究竟有没有${methodName}这个方法。因此,这个组件抛出一个AccessFailureException extends RuntimeException,上层方法不必累赘地声明捕获或者重新throw;因为这样的Exception根本就不应该发生(发生的话,说明你code写得不对),所以一旦发生,程序应该立即fail掉。

何时使用RuntimeException?我斗胆得出个结论:当你想在编译期保证某些编译器检查不出来的错误不会发生,你反而应该使用RuntimeException。
0 请登录后投票
   发表时间:2005-01-23  
我认为Checked Exception是java的一个失败的feature,它几乎就是一种另类的流程控制,且编程不友好(动不动要catch一堆东西,想想你用jdbc时的情景)。而且,我们绝大部分情况下用的是finally来做智源清理,异常只是用来在“异常”时打断当前执行栈,而不是直接抓住它来作处理(有点象COM的HRESULT了)。
0 请登录后投票
   发表时间:2005-04-08  
towjzhou 写道
我认为Checked Exception是java的一个失败的feature,它几乎就是一种另类的流程控制,且编程不友好(动不动要catch一堆东西,想想你用jdbc时的情景)。而且,我们绝大部分情况下用的是finally来做智源清理,异常只是用来在“异常”时打断当前执行栈,而不是直接抓住它来作处理(有点象COM的HRESULT了)。

呵呵,是的。异常根本不该跟方法签名搅到一块,否则异常会象病毒一样在代码中传染。
0 请登录后投票
   发表时间: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是我必须自己维护的。
0 请登录后投票
   发表时间:2005-04-09  
ajoo 写道

但是, 这里, 我仍然被迫做try-catch-rethrow.
这是因为我需要在异常中加入额外的函数名字, 以及其它编译上下文信息来达到错误信息的准确定位.

可以这么想,有三个错误类,CompileParameterException,CompilationFunctionException,CompilationException.
在compileFunction,捕获 CompileParameterException包装成CompilationFunctionException抛出,在compileProgram捕捉再包装成CompilationException.这样看着try-catch-rethrow就合理了,只不过觉得没有必要复杂,把这三个错误类简化成一个类了,但try-catch-rethrow还是保留了.

我会更倾向于让CompileParameter和compile更强耦合.
0 请登录后投票
   发表时间: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的信息...如此一级级传递,层级上的所有元素都会双向耦合。
0 请登录后投票
   发表时间:2005-04-09  
是啊。我同意你对耦合的·看法。看来,重复的rethrow是唯一办法了。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics