昨天正在编码兴头时被项目组xx叫去,说我修改的代码出了空指针异常,还说关键的地方比如这是界面的发起部分,就应该判断是否空指针,不然过不去。我看了一下他的环境,说你没有我的数据库脚本,如果有了数据库环境,应该就不会出现这种情况,然后他就说你这个方法本来就有抛出NullPointerException的可能性,为什么调用完之后不判断呢?而且这是程序的关键部分,出了问题界面都发不起。嗯,好吧,我承认这是我的失误,随即加了if(xxx != null)判断。
对于这件事,引发了我对空指针最佳实践的思考,想必我们使用最多的方法就是在可能发生空指针异常的地方加上:if(xxx != null),每个人都对抛出空指针异常的可能性都不同,换句话说就是这种可能性很难统一和界定,如果使用这种方式,那么代码肯定奇丑难看,到处都是if(xxx != null)else…。而且else部分也不一样,要么什么都不做,要么直接返回提示错误,要么就重新赋一个默认的值。
还有种方式就是在产生return null的地方用new对象代替,这个new对象纯粹是为了防止客户类出现null,可是这样做的可读性降低了,个人认为跟脱了裤子放屁没两样。Api中return null这种写法也比较常见,比较符合OO逻辑。
既然不能避免null,那么你就必须小心翼翼,因为你对每个对象的操作之前你都不能保证它一定是非null,除非你做了判断,Api中为了保证某些值一定不能为null时,采用这种方式:if (name == null) {throw new NullPointerException();}。那我们自己的程序能不能这样写呢?我觉得大多数java程序的现状就是,关键地方使用了if(xxx != null)判断,某些边缘没有判断,所以经常会发生空指针异常。
好像findBugs可以找到可能发生null的地方,不知道它的建议做法是什么?面对NullPointerException,各位有没有更好的做法呢?
====================================================================================
被投隐了,不过没关系,关于几点我还要说明一下,NullPointerException是一个runtimeException,它不会像车checkedException,要么让你“吞掉”,要么让你抛出,就因为它是uncheckedException,所以我们无法精确判断哪个地方会抛出NullPointerException(其实大多数时候是我们根本没有考虑)。
设计模式中有个null object模式,它的大概意思就是对领域对象继承一个null object,它里面什么都不干,代表一个无的概念,用return null object代替return null,这样就避免了NullPointerException的出现。但是个人建议还是要分场合使用,如果return null代表“这段程序不是出现异常了才返回null,而是null本身就代表了一个无的概念”,再现实一点,遍历一个person集合,查找某个person,如果没有查找到,通常我们返回null,这里,就可以用用return null object代替return null了。
是该总结一下空指针的最佳实践了,还是从空指针产生的根源来说:
1.在应用前端,如果null的产生是一个正常的业务逻辑的分支,比如用户的输入,你并没有限制用户可以什么都不干,那么我们就应该使用if(xxx != null)判断,如果为null,我们会给用户一个提示一个对话框,而不是一大堆异常。
2.如果null的产生是应用真正走向了异常边缘,比如环境配置问题,其他前调方法的错误,那么这时就应该大胆的抛出异常,在方法的前置条件使用断言,或者统一判断可能为null的地方,如果为null就抛出NullPointerException,或者什么都不干,大胆的往前走。举一个我实际遇到的例子,方法的入口是一个复合数据结构,但这个复合数据结构是解析xml得来的,有一天,我写的xml格式不对,导致复合数据结构某些引用指向null,那么这个时候,我们就应该大胆的抛出这个异常,让我们早点发现错误的根源,而不是使用if(xxx != null)判断或者使用一个null object导致我们以为什么问题都没有发生,或者感到不对了,却找了半天的问题根源。
3.在合适的情况下,使用null object,就像前面说的,我们在返回return null的时候用return null object代替。
分享到:
相关推荐
= NULL){ strRet = m_iniFile->GetValue("moonlightService", "DIPAddr"); } 4.最后在析构函数记得再判断释放这个碎片化的堆空间(严谨做法) 举例: if (m_iniFile != NULL){ delete m_iniFile; m_...
if (null != bis) { bis.close(); } if (null != fis) { fis.close(); } } catch (IOException e) { e.printStackTrace(); } } return true; } /** * ...
= null || excelWorkBook != undefined) { excelWorkBook.Close(); } if (excelApp != null || excelApp != undefined) { excelApp.Application.Quit(); excelApp = null; } } } ``` 这段代码首先创建了一个...
=`运算符可以安全地用于比较`null`,但`>`、`等运算符会因为无法对`null`进行计算而抛出异常。 #### 4. `xxx == null`与`null == xxx`的等价性 在Java中,`xxx == null`与`null == xxx`是等价的,并且无论哪种写法...
1.在View中显示“您好,我是XXX!”。 2.文本在View内自左向右循环滚动; 3.文字在红、蓝、绿、黄四种颜色之间周期变化。红(255,0,0)蓝(0,255,0)绿(0, 0,255)黄(255,255,0);
= NULL) && (bSrc != NULL)); char* address = aDest; while ((*aDest++ = *bSrc++) != '\0') NULL; return address; } ``` **说明:** 该函数用于将一个字符串复制到另一个字符串中。 #### 2. 字符串比较 `...
=null && Convert.ToBoolean(obj)==true){ //Do something}上面的代码的意图很明显,先判断obj 是不是null,如果不是null 的话,再调用Convert.ToBoolean方法,判断是不是True。 上面的方法没有任何问题,但有一点...
= null && Request.Cookies[strName].Values[subKey] != null) return Server.HtmlEncode(Request.Cookies[strName][subKey].Value); else return null; } } ``` 使用这个类,你可以在应用程序中方便地调用`...
3. **错误检测**:在整个初始化过程中,频繁使用`if(xxx != DD_OK)`的方式进行错误检测,确保每一步操作都正确无误。 ### 结论 通过以上内容,我们可以了解到DirectDraw在游戏开发中的重要性和基本使用流程。...
if (null != zos) { zos.close(); } } } /** * * 功能描述:压缩文件 * 创建者:XXX * 创建日期: 2015年5月7日 - 下午1:37:55 * 版本: V0.1 * 修改者: * 修改日期: ...
== 'object' || left === null) return false; // getPrototypeOf 是 Object 对象自带的 API,能够拿到参数的原型对象 let proto = Object.getPrototypeOf(left); while (true) { if (proto === null) return ...
= null && extension.equalsIgnoreCase(".png")) { return true; } } return false; } public String getDescription() { return "PNG图片"; } private String getExtension(File f) { if (f != null) { ...
#ifnotnull($XXX) 变量$XXX不为null #else 变量$XXX为null #endif ``` #### 方法二:`$null.isNull()` 这是一个更直接的检查方式,无需额外配置。推荐使用此方法,特别是当判断集合对象是否为null时,非常实用。...
if err != nil { log.Fatalf("failed to listen: %v", err) } log.Println("Server is running on port 50051...") if err := server.Serve(lis); err != nil { log.Fatalf("failed to serve: %v", err) } ``` 5....
我自己的VC++课程设计作业。 int k=0; srand((unsigned)time(NULL));... if(j%3!=0) { ofs(4)☆★☆★☆"; } else //三个数换行 数字后面不带符号 { printf("\n"); ofs(4); } } ofs.close();
== "undefined") || (navigator.userAgent.indexOf('IEMobile') !== -1); } if (!isMobileDevice()) { alert("对不起,此页面仅支持移动设备访问。"); // 或者重定向到其他页面 window.location.href = ...
输入名字,程序就会自动问候你,是不是很神奇啊!? 那就快一点下来看看吧!!体验不一样的感觉吧!!
= null and langId != null"> and lang_id = #{langId} </if> ``` 在这个修正后的代码中,`test`属性的条件表达式检查了`_parameter`对象是否存在(即参数不为空)以及`langId`是否不为空。当`langId`有值时,...
= null) rs.close(); if (stmt != null) stmt.close(); if (conn != null) conn.close(); } ``` 6. 结果集的状态:ResultSet有三种状态:未初始化、已移动到下一行和结束。调用next()会改变其状态,且一旦到达...
=,>,<,>=,<=:比较大小,第二个操作数(运算符后面那个)支持IAKIOI,int 时间复杂度,n表示第一个操作数,m表示第二个操作数: 加法:O(max(n, m)) 减法:O(max(n, m)) 乘法:O(nm),抱歉我不会 FFT。 除法:O...