当前位置: 首页 > 科技观察

Java中如何避免空指针异常

时间:2023-03-12 08:19:44 科技观察

这对我来说是一个很合理也很常见的问题,也是初级程序员向中级程序员过渡时经常遇到的问题。他们不知道或不信任正在使用的约定,并且会小心检查是否为空。而他们在写代码的时候,总是依赖于返回NULL来表示什么,所以调用者需要检查是否为Null。换句话说,有两种情况会发生空指针检查:一种是约定俗成的合理响应,一种是不合理的响应;第二种很简单,要么使用assert,要么直接允许失败,比如NullPointerException。断言是从Java1.4添加的一个未被充分利用的特性。语法是:assertorassert:condition是一个布尔表达式,object是一个对象(它的toString()方法会被包含在错误中)。如果条件为假,assert将抛出错误(AssertionError)。默认情况下,Java忽略断言。您可以通过在JVM中传递-ea参数来启用断言。您可以为单个包或类启用和禁用断言。.这意味着您可以在开发和测试期间使用断言验证代码,并在发布到生产环境时将其关闭,尽管我在下面的测试中没有显示断言的性能损失。在这段代码中,不需要断言,因为它会运行失败,就像添加断言一样。唯一的区别是断言可能发生得更快,更有意义,并附上一些额外的信息,可以帮助您找出失败的原因。第一个有点棘手。如果您无法控制被调用的代码,您就会陷入困境。如果Null是一个合理的返回值,您应该检查它。如果它是您可以控制的代码,那就完全不同了。尽量避免使用NULL作为返回值。对于返回Collections的集合,很容易返回Empty(一个空集合或数组),而不是总是返回null。对于不返回Collections的方法来说稍微复杂一些。考虑以下示例:publicinterfaceAction{voiddoSomething();}publicinterfaceParser{ActionfindAction(StringuserInput);}Parser将用户输入作为参数,然后执行某些操作(例如模拟命令行)。现在,如果没有找到输入的操作,您可以返回null,这会导致刚才提到的空指针检查。另一种解决方案是永远不返回null,而是返回一个空对象,publicclassMyParserimplementsParser{privatestaticActionDO_NOTHING=newAction(){publicvoiddoSomething(){/*donothing*/}};publicActionfindAction(StringuserInput){//...if(/*wecan'tfindanyactions*/){returnDO_NOTHING;}}}比较这段代码:Parserparser=ParserFactory.getParser();if(parser==null){//nowwhat?//thiswouldbeanexampleofwherenullisn't(orshouldn'tbe)avalidresponse}Actionaction=parser.findAction(someInput);if(action==null){//donothing}else{action.doSomething();}和这段:ParserFactory。getParser().findAction(someInput).doSomething();这是一个更好的设计,因为它足够简洁,避免了多余的判断。即便如此,也许更合适的设计是findAction()方法抛出异常并显示一些有意义的错误消息——尤其是在您依赖用户输入的情况下。让findAction()方法抛出异常而不是简单地抛出NullPointerException而不做任何解释会好得多。try{ParserFactory.getParser().findAction(someInput).doSomething();}catch(ActionNotFoundExceptionanfe){userConsole.err(anfe.getMessage());}或者你觉得try/catch的机制太丑了,你的action应该向用户提供反馈而不是什么都不做:p??ublicActionfindAction(finalStringuserInput){/*CodetoreturnrequestedActioniffound*/returnnewAction(){publicvoiddoSomething(){userConsole.err("Actionnotfound:"+userInput);}}}