该帖已经被评为良好帖
|
|
---|---|
作者 | 正文 |
发表时间:2010-08-25
最后修改:2010-08-25
用if、Exception还是assert?
|
|
返回顶楼 | |
发表时间:2010-08-26
最后修改:2010-08-26
讲的太复杂了。
总体而言,我推荐用异常控制流程。这样看起来更面向对象一点,而且现代虚拟机的异常处理性能要远远好于禁用异常处理流程的时代。最后,异常抛出的层次不要太深,要及时处理。这样性能问题最大程度上可以避免。 好处是代码看起来更OO,更漂亮简洁。也更容易维护、扩展。 1,对于约定错误,程序员可以通过改善程序代码避免的或者处理的,抛出checked异常 这种错误,有些时候还可以用作流程处理。 比如登陆服务类(如果不用抛出异常处理,代码写的很难看) class UserService{ public User login(String userName,String password){ .... if(null == user) throw new NotFoundUserException("......"); if(user.password != password) throw new PasswordException("......"); if(user.expired) throw new ExpiredException("......"); return user; } } 2,对于数据库连接失败,sql错误等无法通过程序代码处理的异常,抛出unchecked。 |
|
返回顶楼 | |
发表时间:2010-08-26
最后修改:2010-08-26
这个问题我大前年的总结
Java异常有三类:错误,运行时异常,检查型异常。 官方的观点是 第 39 条:最好为异常条件使用异常。也就是说,最好不为控制流使用异常。 第 40 条:为可恢复的条件使用检查型异常,为编程错误使用运行时异常。 第 41 条:避免不必要的使用检查型异常。 第 43 条:抛出与抽象相适应的异常。(使处理异常更直观) 在异常的使用上,专家的观点是很不一样的 C#作者Anders根本就忽略检查型异常。 Bruce Eckel,声称在使用 Java 语言多年后,他已经得出这样的结论,认为检查型异常是一个错误 —— 一个应该被声明为失败的试验。 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 缺点1,代码中包含了过多的catch,使得代码不清晰 缺点2,有时候捕捉的异常没有什么实际意义 缺点3,不够清晰的错误指示。 缺点4,过深的异常层次。 缺点4,性能。 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Eckel 提倡将所有的异常都作为非检查型的,并且提供将检查型异常转变为非检查型异常的一个方法,同时保留当异常从栈向上扩散时捕获特定类型的异常的能力 Rod Johnson ,他采取一个不太激进的方法。他列举了异常的多个类别,并且为每个类别确定一个策略。一些异常本质上是次要的返回代码(它通常指示违反业务规则),而一些异常则是“发生某种可怕错误”(例如数据库连接失败)的变种。Johnson 提倡对于第一种类别的异常(可选的返回代码)使用检查型异常,而对于后者使用运行时异常。在“发生某种可怕错误”的类别中,其动机是简单地认识到没有调用者能够有效地处理该异常,因此它也可能以各种方式沿着栈向上扩散而对于中间代码的影响保持最小(并且最小化异常淹没的可能性)。 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 解决1:谨慎的抛出检查型异常。或者你认为,你可以处理它。否则,包装为运行时异常。 解决2:如果遵守1,2不是问题 解决3:异常不跨层,否则必须捕捉或者包装。 比如持久层丢出的SalException,你或者丢弃/处理/包装(为运行时异常),或者重新包装为业务层异常。保持JEE层的独立和异常的清晰性。 包装底层异常,保持异常链。 解决4:如果符合1,4也不是问题。再次强调,能捕捉就捕捉。 解决5:减少异常使用,减少层次。 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
|
返回顶楼 | |
发表时间:2010-08-26
楼上对异常总结的很好。对于异常处理值得借鉴。
|
|
返回顶楼 | |
发表时间:2010-08-26
polaris1119 写道 实际中应该使用if else或Exception的都有,因而下面的回复也是各抒己见,很多人都有一定的道理。在此先列出几个个人觉得比较靠谱的回复:
5)IcedCoffee:java规范的定义是说异常不要参与控制流程,你不能把异常作为一种正常的控制流程作为程序的一部分,这样是不对的. 面试官正真要考的就是这个.. 没有哪个公司会用异常来处理参数验证.. 楼主大大和IcedCoffee,Google就用异常来处理参数验证: guava-r06 package com.google.common.base; public final class Preconditions { /** * Ensures the truth of an expression involving one or more parameters to the * calling method. * * @param expression a boolean expression * @param errorMessageTemplate a template for the exception message should the * check fail. The message is formed by replacing each {@code %s} * placeholder in the template with an argument. These are matched by * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc. * Unmatched arguments will be appended to the formatted message in square * braces. Unmatched placeholders will be left as-is. * @param errorMessageArgs the arguments to be substituted into the message * template. Arguments are converted to strings using * {@link String#valueOf(Object)}. * @throws IllegalArgumentException if {@code expression} is false * @throws NullPointerException if the check fails and either {@code * errorMessageTemplate} or {@code errorMessageArgs} is null (don't let * this happen) */ public static void checkArgument(boolean expression, @Nullable String errorMessageTemplate, @Nullable Object... errorMessageArgs) { if (!expression) { throw new IllegalArgumentException( format(errorMessageTemplate, errorMessageArgs)); } } /** * Ensures that an object reference passed as a parameter to the calling * method is not null. * * @param reference an object reference * @return the non-null reference that was validated * @throws NullPointerException if {@code reference} is null */ public static <T> T checkNotNull(T reference) { if (reference == null) { throw new NullPointerException(); } return reference; } } |
|
返回顶楼 | |
发表时间:2010-08-26
bugmenot 写道 polaris1119 写道 实际中应该使用if else或Exception的都有,因而下面的回复也是各抒己见,很多人都有一定的道理。在此先列出几个个人觉得比较靠谱的回复: 5)IcedCoffee:java规范的定义是说异常不要参与控制流程,你不能把异常作为一种正常的控制流程作为程序的一部分,这样是不对的. 面试官正真要考的就是这个.. 没有哪个公司会用异常来处理参数验证.. 楼主大大和IcedCoffee,Google就用异常来处理参数验证: guava-r06 package com.google.common.base; public final class Preconditions { /** * Ensures the truth of an expression involving one or more parameters to the * calling method. * * @param expression a boolean expression * @param errorMessageTemplate a template for the exception message should the * check fail. The message is formed by replacing each {@code %s} * placeholder in the template with an argument. These are matched by * position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc. * Unmatched arguments will be appended to the formatted message in square * braces. Unmatched placeholders will be left as-is. * @param errorMessageArgs the arguments to be substituted into the message * template. Arguments are converted to strings using * {@link String#valueOf(Object)}. * @throws IllegalArgumentException if {@code expression} is false * @throws NullPointerException if the check fails and either {@code * errorMessageTemplate} or {@code errorMessageArgs} is null (don't let * this happen) */ public static void checkArgument(boolean expression, @Nullable String errorMessageTemplate, @Nullable Object... errorMessageArgs) { if (!expression) { throw new IllegalArgumentException( format(errorMessageTemplate, errorMessageArgs)); } } /** * Ensures that an object reference passed as a parameter to the calling * method is not null. * * @param reference an object reference * @return the non-null reference that was validated * @throws NullPointerException if {@code reference} is null */ public static <T> T checkNotNull(T reference) { if (reference == null) { throw new NullPointerException(); } return reference; } } 其实这段代码跟Java API的实现方式很类似。对于Java API的实现方式,已经有所解释了。 如果写应用,我觉得 public static <T> T checkNotNull(T reference) { if (reference == null) { throw new NullPointerException(); } return reference; } 类似的方法更多的写法是:返回一个boolean类型,if判断是否为null,然后返回false或true。 另外, if (reference == null) { throw new NullPointerException(); } 这样的方式到底是if控制流程呢,还是异常?似乎应该是两者结合吧。 不对之处,请指正。 |
|
返回顶楼 | |
发表时间:2010-08-26
看到那贴如此踊跃的发言,真的很欣慰啊 ,很感谢大家的讨论啊,学到了很多 ...
也很谢谢您的总结,对断言也更了解了. 面试的时候我的回答是: 如果是共用的接口,并且需要用返回值的,就用Exception,让调用方知道该方法可能出现的异常(checked exception). 如果只是个类的内部私有方法,直接if else了. 看了这么多讨论.貌似也挨着到边了.呵呵... |
|
返回顶楼 | |
发表时间:2010-08-26
条件不符合, 这本身就是一个异常, 抛出exception是必须的
这种话题还有这么多人讨论。 |
|
返回顶楼 | |
发表时间:2010-08-26
最后修改:2010-08-26
Checked Exception就是我们固定洲际导弹,就在那架着给别人看,随时可能发射。任何和我们打交道的都必须提前考虑好把我们惹毛了怎么接着核弹。
Unchecked Exception机动的洲际导弹,就没打算让你提前防着,怒了直接就扔出去,谁也别想拦着。当然你拦住了我也没办法。 检查个输入参数需要动用洲际导弹吗?自己看情况,一看国家类型(比如朝鲜...),二看输入的是什么东西(人家给你你扔个核弹进来...)。 断言那就是真理部的各类禁令,也就自己乐呵乐呵吧,拿不出手的。 |
|
返回顶楼 | |
发表时间:2010-08-26
总结之后:按需操作。
|
|
返回顶楼 | |