Java中空指针异常该如何避免详解
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Java中空指针异常该如何避免详解
Java中如何避免空指针异常,这也是由初级程序员成长到中级程序员的时候经常会遇到的问题。
程序员不知道或不信任正在使⽤的约定,并且⼩⼼的检查着null。
还有当程序员写代码的时候,总是会依赖于通过返回空(NULL)来表明某些意义,因此需要调⽤者去检查Null。
有两种空指针的检查场景:
期望的结果就是null。
期望的结果不是null。
第⼆种很简单,可以通过⽤assert或者允许程序报错,例如抛出NullPointerException。
Assertions是⼀个从Java1.4加进来的⾼度未被利⽤的特性,语法是:
assert <condition>
或者
assert <condition> : <object>
condition是⼀个布尔表达式,object是⼀个对象(其toString()⽅法的输出将会被包含在错误⾥)。
校对注:我测试了下,JDK1.4及其以上,运⾏前设置vm参数-ea
public static void main(String[] args) {String name = null;assert (name != null) : "name为空null";}
Exception in thread "main"; ng.AssertionError: 变量name为空nullat LogUtil.main(LogUtil.java:37)
如果condition为false的话,assert将会抛出⼀个Error(AssertionError)。
默认Java会忽略断⾔你可以通过在JVM中传⼊⼀个-ea 参数来启⽤断⾔。
你可以为单独的⼀个包或者类启动关闭assertions。
这意味着你可以在开发和测试的时候通过断⾔来验证代码,在发布产品的时候关闭它,尽管我下⾯展⽰的测试中并没有因为assertions⽽损失性能。
在这个代码段中不⽤断⾔也可以,因为他会运⾏失败的,就像加了断⾔⼀样。
唯⼀的区别是有了断⾔可能会发⽣的更快⼀些,更有意义,并且会附加⼀些额外的信息,⽽这可以帮助你弄明⽩失败的原因。
第⼀种有⼀点棘⼿。
如果你对不能控制正在调⽤的这段代码,那你就卡住了。
如果Null是⼀个合理的返回值,你就应该检查它。
如果是你能够控制的代码,那就是个完全不同的故事情景了。
尽量避免⽤NULL作为返回值。
对于返回Collections的集合很容易,返回Empty(⼀个空集合或者数组),⽽不是⼀直⽤null作为返回值。
对于不是返回Collections的⽅法会有⼀点复杂。
考虑下⾯这个例⼦:
public interface Action {
void doSomething();}public interface Parser {
Action findAction(String userInput);}
Parser采⽤⽤户的输⼊作为参数,然后做⼀些事情(例如模拟⼀个命令⾏)。
现在你可能会返回null,如果没找到对应输⼊的动作的话,这就导致了刚才说过的空指针检查。
⼀个可选的解决⽅案是永远不要返回null,⽽是返回⼀个空对象
public class MyParser implements Parser {
private static Action DO_NOTHING = new Action() {
public void doSomething() { /* do nothing */ }
};
public Action findAction(String userInput) {
// ...
if ( /* we can't find any actions */ ) {
return DO_NOTHING;
}
}}
⽐较这段代码:
Parser parser = ParserFactory.getParser();if (parser == null) {
// now what?
// this would be an example of where null isn't (or shouldn't be) a valid response}Action action = parser.findAction(someInput);if (action == null) {
// do nothing} else {
action.doSomething();}
和这段:
ParserFactory.getParser().findAction(someInput).doSomething();
这是个更好的设计,因为⾜够简洁,避免了多余的判断。
即便如此,或许⽐较合适的设计是:findAction()⽅法之恶杰抛出⼀个异常,其中包含⼀些有意义的错误信息—–特别是在这个案例中你依赖于⽤户的输⼊。
让findAction()⽅法抛出⼀个异常⽽不是简单的产⽣⼀个没有任何解释的NullPointerException 要好得多。
try {
ParserFactory.getParser().findAction(someInput).doSomething();} catch(ActionNotFoundException anfe) {
userConsole.err(anfe.getMessage());}
或者你认为try/catch 的机制太丑了,你的action应该跟⽤户提供⼀个反馈⽽不是什么都不做:
public Action findAction(final String userInput) {
/* Code to return requested Action if found */
return new Action() {
public void doSomething() {
userConsole.err("Action not found: " + userInput);
}
}}
补充:个⼈在做项⽬时,对NullPointerException的⼏点总结,请⽹友拍砖多多提意见,
1.对于别⼈接⼝的返回对象要做⾮空判断,因为我们不清楚获得的对象会不会为空,对于Collection Map 我⼀般会调⽤CollectionUtils MapUtils ,对于返回的String对象,我会调StringUtils.isNotEmpty()进⾏⾮空判断。
他们中isNotEmpty不仅判断了NULL 还判断了空集合和空串。
例如从数据中查询的结果。
⼯作流中返回的定价URL
2. 对于⾃⼰创建的对象,要留⼼对象进⾏哪些操作,中间会不会造成对象为空,如果可能加⾮空判断,尤其是对于集合的操作,很容易就报空指针所以每次对操作集合时,我都会⾮常的留⼼。
3. 对于前台的领域对象要⾮常的留⼼,因为这些对象是框架创建的,假如我没有在前台的⽂本框内输⼊值,虽然提交时后台获得的是空串,但发⽣NullPointerException的概率很⾼。
4. 对于String 的操作尽量使⽤apache 的StringUtils类,与String相⽐这个是⾮常的安全。
对于集合的操作使⽤apache的CollectionUtils 、MapUtils, 相⽐apache⼯具类的执⾏效率也⾮常的⾼,⽐如StringUtils.split();
有⼈说过多的判断会影响性能,我个⼈认为这⾥的性能牺牲和系统的安全相⽐是微不⾜道的。
总结
到此这篇关于Java中空指针异常该如何避免的⽂章就介绍到这了,更多相关Java空指针异常内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!。