`

用if、Exception还是assert? ——看JavaEye论坛帖子:《面试题:用Exception异常还是if判断》的感想

    博客分类:
  • Java
阅读更多

用if、Exception还是assert? 
          ——看JavaEye论坛帖子:《面试题:用Exception异常还是if判断》的感想

今天在JavaEye上看到一个很火的帖子,题目是:面试题:用Exception异常还是if判断http://www.iteye.com/topic/745640。内容大概是: 
    当参数不合法的时候,究竟是if else 判断后返回一个值还是直接来个Exception ? 
    如果是 if else 的话,有什么好处 ? 
    如果是 exception 的话,又有什么好处 ? 
    或者是根据不同情况来定?

 

实际中应该使用if else或Exception的都有,因而下面的回复也是各抒己见,很多人都有一定的道理。在此先列出几个个人觉得比较靠谱的回复:

 

1)sam_chi:看情况吧,如果能在方法里面处理不影响方法功能的话使用if else处理,如果参数错误导致方法不能正常工作,那么就得抛异常了,Java提供了java.lang.IllegalArgumentException,可以直接new一个抛出去,这是一个RuntimeException,不需要try..catch。

2)mercyblitz:if-else 方式的好处在于更贴近与逻辑思维,性能优于Exception。相对于Exception,其缺点是,不适合OOP,语义不明显,不易于错误错误跟踪或错误提示较少,并且类型比较单一(比如利用C语言的原生类型)或者难以统一(比如C语言结构和宏定义)。 
exception方法的好处在于是业务逻辑和异常处理分离(代码相对清晰),try中处理业务,catch中处理异常情况。在API设计中,可以设计Exception Handler来处理异常,使得层次分明。同时,更好的OOP的封装和多态性。缺点在于性能相对差。

3)fireaap:根据情况来选择使用if...else,还是exception。选择的依据就是,你的方法的职责。也可以说是你方法的契约。

4)konser:sam_chi 说的很对,首先大家要明白什么是异常,异常就是程序不能正常执行,错误的调用api的方法,资源失败等等原因 。程序逻辑又是一回事。为什么要把异常和逻辑判断混合起来做对比?  补充一下如果,当参数不合法的时候抛出IllegalArgumentException . 
如果是 if else 的话,有什么好处 ? 
参数不合法程序都不能正常执行了那你说有啥好处? 
如果是 exception 的话,又有什么好处 ? 
面向对象的思维,抛出每个异常时可根据不同异常以不同方式进行处理 。缺点是创建消耗内存,效率低。

5)IcedCoffee:java规范的定义是说异常不要参与控制流程,你不能把异常作为一种正常的控制流程作为程序的一部分,这样是不对的. 
面试官正真要考的就是这个.. 
没有哪个公司会用异常来处理参数验证..

6)liupopo:先要明确异常是做什么的,异常是程序执行时的一些非正常的情况,如果有不正确的数据、逻辑等会抛出异常。 
if else是逻辑判断,控制程序流程。 
断言是预先决断应该是什么样的值,不应该是什么类型等明确的条件 
从定义上不太好区分这些怎么去用,但可以从使用场景去考虑,下面的可能不十分准确,但大家可以参考一下: 
异常:是程序员写给其他程序员的,比方说我写了一个方法,如果其他人使用我这个方法的时候有可能不按我想的路子使用,可能会引起我的方法产生不正常的处理,这时候我要使用异常,而且可以决定产生异常了是由我这个方法本身进行处理(catch语句中处理)还是交给调用者进行处理(直接把异常抛出) 
if else 就是我写的方法,要进行逻辑判断,就用它,没什么好说的吧。 
断言可用处大了,是我在调用别人写的方法,或者我处理程序时对通过其他途径得到的数据(如调用别人方法的返回值(好象不建议用断言),通过参数传入的值)等进行假设它就是某值时使用的。是方便开发、调试提供的一个语法元素

7)JonyUabka:1对可预见的运行时异常当进行捕捉并处理,比如空指针等。通常,对空指针的判断不是使用捕捉NullPointException的方式,而是在调用该对象之前使用判断语句进行直接判断,如: 
//若不对list是否为null进行检查,则在其为null时会抛出空指针异常 

if(null != list && 0 < list.size()){ 
for(int i = 0; i &lt; list.size(); i++){ 
} 
} 

 2对于经常发生的可预计事件不要采用异常 
3不要使用异常实现控制结构。 
4通常的思想是只对错误采用异常处理:逻辑和编程错误,设置错误,被破坏的数据,资源耗尽,等等。 
对于java的编码规范,有具体描述。我想考官希望得到的是这个方向的答案。

8)maomaolingyu: 
if else 
优点: 
A 逻辑自己控制,清晰 
缺点: 
A 当情况复杂时 需要过多的if else .导致逻辑难以理解 
B 容易存在漏洞,导致错误或者不期望的结果 
Exception 
优点: 
A 异常通过异常链传播且会被jvm自动捕捉,减少逻辑代码 
B 异常很容易确定代码问题段,方便测试 
缺点: 
A 当异常发生但是没有正确捕获时,会异常抛出到用户页面.

引用了这么多,下面谈谈本人的一点看法,不对之处敬请指正。

首先,对于这个问题,不应该回答:用Exception异常或者if判断,而应该视情况决定使用Exception还是if。个人觉得面试官比较看重的是你对异常的理解,回答的关键应该是两者的优缺点与适用场合上,顺带可以总结一些实际中你是如何处理异常的。对于有人说使用断言(assert),还说是标准答案,本人实在不赞同。就像有人回答说:题目问的是:用Exception异常还是if判断,却来个用断言,太离题了吧。而且这么回答的话,下面的问题怎么答?难道直接说他们都不好,assert好?

本人觉得liupopo说的靠谱。下面结合一些代码来说明一些问题。

在此之前,就像不少人说的一样,先要明确什么是Exception。《The Java Language Specification 3.0》中有这么一句描述:When a program violates the semantic constraints of the Java programming language, the Java virtual machine signals this error to the program as an exception.大意是:当程序违反Java语言的语义约束时,Java虚拟机会将这个错误(异常)发送给程序。

下面进入正题:

 

1、看Java API如何处理的

本人查看了DateFormat、Integer等类的源码,分析如下:

1.1 public final String format(Date date)方法

该方法的参数date只有一种情况是不正确的:null。然而,阅读源码发现并没有判断该参数是否为null。那么当为null时(违反了Java语言的语义),异常NullPointerException自然而然是JVM自动抛出的,而不是API通过throw抛出的。

1.2 public static Integer valueOf(String s, int radix) throws NumberFormatException方法

该方法有两个参数,第一个String类型的参数有可能为null,而方法声明抛出NumberFormatException异常,因而有一段if判断: 
        if (s == null) { 
            throw new NumberFormatException("null"); 
        } 
对于radix参数有不少限制,因而源码中进行了几个if判断: 
        if (radix &lt; Character.MIN_RADIX) { 
            throw new NumberFormatException("radix " + radix + 
                            " less than Character.MIN_RADIX"); 
        }

        if (radix > Character.MAX_RADIX) { 
            throw new NumberFormatException("radix " + radix + 
                            " greater than Character.MAX_RADIX"); 
        } 
后面还有几个其他的判断。

总结:在论坛中,有人提到在JDK源码中,经常可以看见类似 
        if (s == null) { 
            throw new NumberFormatException("null"); 
        } 
这样的代码。借用liupopo的话,JDK中的方法是写给Java程序员调用的,而且Java有自己内部的一套异常机制。比如,对于format()方法抛出的NullPointerException异常,JDK不可能自己进行处理,出现该异常是:这个方法的时候没按它的路子使用,我们要使用该方法就应该确保传入的Date参数不是null,即需要进行if判断,对于valueOf方法一样如此,调用方法前就应该对是否为null值进行if判断(或确保非null)。从JDK的处理radix参数的方法我们可以看出,if经常与Exception结合使用,if用于处理逻辑,Exception用于告诉用户“有问题”。所以,如果你写的代码是给其他人使用的,你需要考虑是否抛出异常,这个时候对于参数的判断更多的应该使用JDK这种方式:对于非法参数,if判断后,包装为统一的Exception抛出,当然异常也有可能没必要抛出,而是自己处理(各种开源框架中都有这样情况)。

2、现在推荐的Java异常机制

Java API在设计的时候大量使用了checked exception,当时很推荐这种方式。然而,用过Spring的人都知道,Spring中大量使用了unchecked exception即RuntimeException。《thinking in java》的作者Bruce Echel说:“当少量代码时,checked异常无疑是十分优雅的构思,并有助于避免了许多潜在的错误。但是经验表明,对大量代码来说结果正好相反”。很多时候对于Java API抛出的异常,程序员都不知道怎么处理,比如SQLException,大家无非就是catch,然后e.printStackTrace(),或者什么也不做,这样导致程序中很多的try...catch...,既然如此,那么抛出checked exception就没有必要了,而且抛出uncheck exception不会污染接口。对于异常处理的问题很是有必要研究研究的。

既然推荐使用uncheck exception,结合Exception本身的特点,在写应用程序(不是提供给其他开发人员的API)时,参数的判断应该更多的使用if,毕竟参数错误的情况不会很多。

另外,有人建议使用Java自己的IllegalArgumentException异常进行判断,当然这有时候也是可行的。比如,有些时候参数没法活很难通过if来判断(因为我们不知道非法参数会是什么),这个时候可以使用该异常。

其实,很多时候,对参数合法性检查时,需要考虑方法的返回值。比如,接收一个Date类型参数,然后返回一个对应的String类型在页面上显示(该参数不是必须的,比如生日),这个时候,如果Date类型参数为null,我们不应该抛出NullPointerException,而应该用if进行如下判断: 
        if(date==null) { 
            return ""; 
        } 
返回空字符串很合理,这样页面就会显示空白(相当于没填)。其他情况,如返回值为boolean类型,很可能参数非法时会返回false。视具体情况而定。

3、关于断言(assert)

论坛回复中有人力推assert来判断参数合法性。不知道是没有理解题目的意思还是对断言本身不够了解,亦或对断言情有独钟。对于该面试题,可以肯定的是,用断言(assert)绝对是错误的。断言只是程序员测试和调试的一个工具,发布后一般也不会开启的,而且,Java规范也建议这么做。而参数是否合法性却总是存在的,所以用断言是完全错误的。

关于Java的assert,本人几乎没使用过,也很少见人使用。对程序进行测试或调试,更多的是使用JUnit或IDE的Debug功能,他们已经工作的很好了。在网上找到一篇很有意思的文章,他是痛批java的assert(Java陷阱之assert关键字),感兴趣的可以读读。个人不完全同意其观点,Java引入assert应该有其好处。

在这里把《The Java Language Specification 3.0》中对assert的描述做个总结。

3.1 assert的语法

assert语句有两种形式语法: 
    assert 表达式1 ; 
    assert 表达式1 : 表达式2 ; 
其中,表达式1的值必须是boolean类型,否则会编译错误。这里boolean类型有两种形式:1)var1==var2;2)var=true。其中第二种形式var是boolean类型,一般应该使用第一种形式,而第二种形式往往是程序员失误造成的。表达式2的值可以是除了void之外的任何类型。

3.2 断言开启时机

默认情况下断言没有开启。可以选择在哪个类上启用断言(断言启用没有继承性)。在类字段初始化器和静态初始化器初始化之前,类的类装载器根据配置决定启用或禁用断言。一旦类初始化完成后,断言的状态(启用或禁用)没法再改变。

然而,在规范中提到了一种例外情况:类层次结构之间的循环情况(实际中几乎不会这么做)。例子程序如下: 
        public class Foo { 
            public static void main(String[] args) { 
                Baz.testAsserts(); 
                // Will execute after Baz is initialized. 
            } 
        }

        class Bar { 
            static { 
                Baz.testAsserts(); 
                // Will execute before Baz is initialized! 
            } 
        }

        class Baz extends Bar { 
            static void testAsserts() { 
                boolean enabled = false; 
                assert enabled = true; 
                System.out.println("Asserts " + (enabled ? "enabled" : "disabled")); 
            } 
        } 
调试运行会发现,在assert没有开启的情况下,第一次输出的结果却显示assert已开启,当然第二条语句显示没有开启(注意,如果assert没开启,assert enabled = true这条语句是没有效果的)。这是说明,当断言语句在类初始化之前执行时,结果就如同开启了assert。(Polaris在调试时,发现一个奇怪的现象:就是第一次执行testAsserts方法时,单步调试,assert enabled = true;语句似乎跳过去了,不过结果却显示该语句是执行了的。很奇怪。)

关于断言的开启方法,控制台开启,IDE开启可以上网搜索,在此不介绍。

3.3 使用断言的注意事项

Java规范中对于断言语句的执行有详细的说明,有兴趣的朋友可以参阅http://java.sun.com/docs/books/jls/third_edition/html/statements.html#14.10

关于assert抛出的AssertionError,规范上建议不要捕获。

由于断言有可能没有开启,因而程序千万不要假定断言中的表达式会被计算,即不能依赖断言的结算结果(表达式1的值),所以,表达式1可能会产生一定的副作用:

1)assert语句虽然可以有副作用,如上面提到的表达式1返回boolean类型的第二种形式,然而这通常是不合适的,因为这可能导致依赖此值的程序在assert启用或禁用时有不同结果;

2)不要使用断言作为公共方法的参数检查,公共方法的参数永远都要执行。这一点可以很好的解释为什么说使用断言来判断参数合法性是错误的,尽管断言有时候可以用于检查传递给私有方法的参数。

Java规范在讲解断言副作用时,还说到了erroneous arguments should result in an appropriate runtime exception (such as IllegalArgumentException, IndexOutOfBoundsException or NullPointerException),即错误的参数检查应该产生一个合适的运行时异常。

在网上看到有总结使用断言的情况:(列举出来供参考)

1)可以在预计正常情况下程序不会到达的地方放置断言 :assert false  
2)断言可以用于检查传递给私有方法的参数。(对于公有方法,因为是提供给外部的接口,所以必须在方法中有相应的参数检验才能保证代码的健壮性)  
3)使用断言测试方法执行的前置条件和后置条件 
4)使用断言检查类的不变状态,确保任何情况下,某个变量的状态必须满足。(如age属性应大于0小于某个合适值)

3.4 Polaris的建议

要进行调试或测试,可以使用IDE或JUnit。

说了这么多希望对大家有个参考作用,同时不对之处敬请批评指正。

分享到:
评论
24 楼 Mr_sqw 2015-02-08  
bonny 写道
这个问题我大前年的总结


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:减少异常使用,减少层次。

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

 


官方的观点 在哪找?
23 楼 Mr_sqw 2015-02-08  
IcedCoffee 写道
awfe 写道
Checked Exception就是我们固定洲际导弹,就在那架着给别人看,随时可能发射。任何和我们打交道的都必须提前考虑好把我们惹毛了怎么接着核弹。

Unchecked Exception机动的洲际导弹,就没打算让你提前防着,怒了直接就扔出去,谁也别想拦着。当然你拦住了我也没办法。

检查个输入参数需要动用洲际导弹吗?自己看情况,一看国家类型(比如朝鲜...),二看输入的是什么东西(人家给你你扔个核弹进来...)。

断言那就是真理部的各类禁令,也就自己乐呵乐呵吧,拿不出手的。


比喻的生动活泼...


22 楼 hardwin 2010-12-22  
polaris1119 写道
贫嘴男孩 写道
polaris1119 写道
贫嘴男孩 写道
大家的事务在什么地方控制的?我在service使用异常,因为不用异常无法做到事务回滚。

Spring管理事务的话,默认出现RuntimeException时回滚的,所以不需要在service中显示抛出异常。一般事务都在service中控制的吧。

有些业务上的逻辑异常不也得在service上抛吗

最好在这样的异常在service中就处理了,或者封装成RuntimeException再抛出。


那没有使用spring这种框架的情况呢?自己写的数据库工具类,事务处理在工具类中处理,而database utility是需要给别人调用的。

这样,dbutil是应该在方法上直接把异常往外抛哦?是否使用事务,使用一个标示值,由调用方指定此值。dbutil只提供方法,不处理提交、回滚。提交,回滚让调用方去做。dbutil我全部使用的throws Exception。

异常抛的太大不好吧?
21 楼 ldbjakyo 2010-09-19  
异常的使用是很有必要深入了解的
20 楼 polaris1119 2010-09-19  
贫嘴男孩 写道
polaris1119 写道
贫嘴男孩 写道
大家的事务在什么地方控制的?我在service使用异常,因为不用异常无法做到事务回滚。

Spring管理事务的话,默认出现RuntimeException时回滚的,所以不需要在service中显示抛出异常。一般事务都在service中控制的吧。

有些业务上的逻辑异常不也得在service上抛吗

最好在这样的异常在service中就处理了,或者封装成RuntimeException再抛出。
19 楼 贫嘴男孩 2010-09-19  
polaris1119 写道
贫嘴男孩 写道
大家的事务在什么地方控制的?我在service使用异常,因为不用异常无法做到事务回滚。

Spring管理事务的话,默认出现RuntimeException时回滚的,所以不需要在service中显示抛出异常。一般事务都在service中控制的吧。

有些业务上的逻辑异常不也得在service上抛吗
18 楼 polaris1119 2010-09-19  
贫嘴男孩 写道
大家的事务在什么地方控制的?我在service使用异常,因为不用异常无法做到事务回滚。

Spring管理事务的话,默认出现RuntimeException时回滚的,所以不需要在service中显示抛出异常。一般事务都在service中控制的吧。
17 楼 贫嘴男孩 2010-09-19  
大家的事务在什么地方控制的?我在service使用异常,因为不用异常无法做到事务回滚。
16 楼 yunmanfan 2010-08-27  
这个问题值得这么讨论吗?实际中不都是两者结合用的吗?我晕.
15 楼 zhajie 2010-08-26  


异常的字面解释就是异乎寻常,当然包括业务层的不寻常。

if else 不说了。如果业务复杂,都难以想象,怎么绕出来。
14 楼 kingwood2005 2010-08-26  
我觉得还是要看具体情况,而且那个面试题本来的意思也就要你回答用Exception异常还是if判断的具体情况。
13 楼 JE帐号 2010-08-26  
讨论个问题,终止流程算不算控制流a?
考虑一下一个三层的嵌套调用.
如果是if,else 控制,在结果可能情况较多时,就给返回相应的code,这样如果在第二层拿到第三层的code,是将code直接返给第一层还是说自己再做变换后返回?
如果不转换,那么第一层就给知道第三层的code定义,那么作为第一层似乎知道的有点多了.如果转换了一二层约定的code,第二层自己的事又多了.
如果是Exception,那么在每个层出现错误只要抛出自己的Exception即可.
由于每层的Exception的具体类型不同,所以只需要每层自己在提供一个由自己层抛出的Exception的处理handle即可.
各位实际中如何处理的?
12 楼 polaris1119 2010-08-26  
同意楼上的观点。
11 楼 IcedCoffee 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;
  }
}


这其实就是用if{}else{}来处理业务逻辑了..
如果条件不满足就抛出异常..这是对的啊..不矛盾..

java规范里说的不能用异常机制参与业务逻辑是指用try catch来控制流程这样是不对的..
10 楼 IcedCoffee 2010-08-26  
awfe 写道
Checked Exception就是我们固定洲际导弹,就在那架着给别人看,随时可能发射。任何和我们打交道的都必须提前考虑好把我们惹毛了怎么接着核弹。

Unchecked Exception机动的洲际导弹,就没打算让你提前防着,怒了直接就扔出去,谁也别想拦着。当然你拦住了我也没办法。

检查个输入参数需要动用洲际导弹吗?自己看情况,一看国家类型(比如朝鲜...),二看输入的是什么东西(人家给你你扔个核弹进来...)。

断言那就是真理部的各类禁令,也就自己乐呵乐呵吧,拿不出手的。


比喻的生动活泼...
9 楼 ristaju 2010-08-26  
总结之后:按需操作。
8 楼 awfe 2010-08-26  
Checked Exception就是我们固定洲际导弹,就在那架着给别人看,随时可能发射。任何和我们打交道的都必须提前考虑好把我们惹毛了怎么接着核弹。

Unchecked Exception机动的洲际导弹,就没打算让你提前防着,怒了直接就扔出去,谁也别想拦着。当然你拦住了我也没办法。

检查个输入参数需要动用洲际导弹吗?自己看情况,一看国家类型(比如朝鲜...),二看输入的是什么东西(人家给你你扔个核弹进来...)。

断言那就是真理部的各类禁令,也就自己乐呵乐呵吧,拿不出手的。
7 楼 godfish 2010-08-26  
条件不符合, 这本身就是一个异常, 抛出exception是必须的

这种话题还有这么多人讨论。
6 楼 showr 2010-08-26  
看到那贴如此踊跃的发言,真的很欣慰啊 ,很感谢大家的讨论啊,学到了很多 ...

也很谢谢您的总结,对断言也更了解了.

面试的时候我的回答是:

如果是共用的接口,并且需要用返回值的,就用Exception,让调用方知道该方法可能出现的异常(checked exception).

如果只是个类的内部私有方法,直接if else了.

看了这么多讨论.貌似也挨着到边了.呵呵...
5 楼 polaris1119 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控制流程呢,还是异常?似乎应该是两者结合吧。

不对之处,请指正。

相关推荐

    java程序员面试题——863面试集

    ### Java程序员面试题详解 #### 一、Java基础知识 1. **作用域public, private, protected, 以及不写时的区别** - **public**: 可以被任何类访问。 - **protected**: 可以被同一包内及不同包内的子类访问。 - ...

    090830 Java面试题——基础篇60题

    ### Java面试题——基础篇60题解析 #### 1. 作用域 public,private,protected 以及不写时的区别 在Java中,类成员(如变量、方法等)的作用域可以通过不同的修饰符来控制。具体如下: - **public**:公开的,...

    assert-exception:断言异常功能(抛出拒绝)

    断言异常 安装 $ yarn add -D assert-exception # or $ npm install assert-exception --save-dev 用法 没有assert-exception import assert from 'power-assert' ; assert . throws ( ( ) =&gt; { throw new Error ...

    Java后端面试题

    ### Java面试题知识点概览 #### 面向对象概念 1. **super()与this()的区别**: - `super()`用于调用父类的构造方法或父类成员方法。 - `this()`用于调用本类中的其他构造方法。 2. **作用域public, protected, ...

    Java面试题大全及答案(归类).doc

    ### Java面试题详解 #### 一、访问修饰符的作用范围 **问题:** 作用域`public`, `private`, `protected`, 以及不写时的区别是什么? **解答:** - **public:** 具有全局可访问性,即可以在任何地方被访问。 - **...

    业务异常提示处理 springboot+Assert(自定义断言)

    在IT行业中,异常处理是系统稳定性和健壮性的重要组成部分,尤其是在使用Spring Boot进行Web开发时。本项目“业务异常提示处理 springboot+Assert(自定义断言)”着重于利用Spring Boot的特性来构建高效、易维护的...

    java面试题

    答:控制流程一般使用if判断条件。有第二分支,多分支,循环结构。循环本质上也是通过判断来实现的。 多形与继承? 答:多形:一个类中多个同名方法。继承:子类继承父类。 jsp内置对象? 答:request 用户端请求 ...

    Java 面试题 Java 面试题

    根据给定的文件内容,我们可以总结出一系列与Java面试相关的知识点。下面将详细解析每一道题目涉及的关键概念。 ### 第一部分:基础知识 #### 1. final, finally, finalize的区别 - **final**: 用于声明变量、方法...

    北大青鸟JAVA面试题

    从给定的文件信息中,我们可以提炼出一系列与北大青鸟JAVA面试相关的知识点,这些知识点涵盖了JAVA编程语言的基础概念、异常处理、面向对象特性、线程管理、内存管理以及垃圾回收机制等关键领域。下面是对这些知识点...

    java笔试题

    ### Java笔试题详解 #### 一、访问修饰符的...**解答**: 常见的运行时异常包括但不限于`ArithmeticException`(算术异常)、`ArrayStoreException`(数组存储异常)、`BufferOverflowException`(缓冲区溢出异常)。

    c++ 各权威公司面试题

    《C++面试题解析:深度剖析strcpy函数与内存安全》 C++面试中,考察面试者的技术水平往往从基础开始,而基础中的基础莫过于对字符串处理的理解,特别是经典的strcpy函数。本文将通过分析一系列面试题,揭示其中的...

    c 经典面试题经典版

    《C语言经典面试题解析》 面试是评估潜在员工技能的重要环节,对于C/C++程序员而言,面试中常出现的经典问题往往围绕基础概念、编程技巧和逻辑思维能力。本文将深入探讨一些常见的C语言面试题,帮助你了解面试官...

    最新最全Java面试题汇总

    ### 最新最全Java面试题汇总 #### 1. Java中的访问控制修饰符:public, private, protected 及默认(friendly) 在Java中,我们有四种主要的访问控制级别,它们分别是 `public`、`private`、`protected` 和默认...

    java面试题总结

    ### Java面试题总结知识点 #### 1. J2EE是什么? - **定义**:J2EE(Java 2 Platform, Enterprise Edition)是一个基于Java SE平台的企业级应用开发平台标准,由Sun Microsystems制定。 - **组成**:J2EE平台包含...

    面试题大全

    面试是评估求职者技能的重要环节,尤其是对于C/C++程序员,面试题往往能揭示出候选人在基础概念、编程技巧和问题解决能力上的水平。以下是一些常见的面试题及其涉及的知识点: 1. **字符串处理**: - **strcpy函数...

    新手必看的java经典面试题

    ### 新手必看的Java经典面试题解析 #### 1. Java中的访问修饰符:`public`, `private`, `protected`, 默认(friendly) 在Java中,我们有四种访问级别: - **`public`**:公开的,任何地方都可以访问。 - **`...

    JAVA程序员面试题(含有答案)经典版

    本文总结了 Java 程序员面试题中的一些重要知识点,涵盖了异常处理机制、垃圾回收、Error 和 Exception 的区别、final、finally 和 finalize 的区别、 Anonymous Inner Class、Static Nested Class 和 Inner Class ...

    嵌入式LinuxC语言面试试题1.pdf

    嵌入式LinuxC语言面试试题1.pdf 这份面试试题涵盖了C语言的基础知识、ANSI C/C++方面的知识、指针数组、字符数组、编程语言、编译器、词法分析、常量字符串、局部变量、malloc函数、realloc函数、strtok函数、gets...

    史上最全的C程序员面试题

    在准备C语言程序员的面试时,了解各类面试题并深入理解其背后的原理是至关重要的。以下是一些基于“史上最全的C程序员面试题”及“面试题 c”标签的常见问题和相关知识点的详尽解释: 1. **基础概念:** - **变量*...

    java经典面试题.doc

    ### Java经典面试题知识点解析 #### 1. super()与this()的区别? - **super()**:用于调用父类的构造方法。在一个子类的构造方法中,如果要调用父类的构造方法,必须使用`super()`,并且这个调用语句必须放在子类...

Global site tag (gtag.js) - Google Analytics