大家好,关于面试官揭秘:如何在工作场合预防十亿美元级的NPE错误很多朋友都还不太明白,不过没关系,因为今天小编就来为大家分享关于的知识点,相信应该可以解决大家的一些困惑和问题,如果碰巧可以解决您的问题,还望关注下本站哦,希望对各位有所帮助!
公共类NpeDemo{ 公共静态void main(String[] args){ NpeDemo npeDemo=null; npeDemo.go(); }}
执行上述程序时,会报NPE:
线程“main”中的异常java.lang.NullPointerExceptionat NpeTest.main(NpeTest.java:4)
通过像上面这样简单的方法,我们就可以根据堆栈信息快速找到问题所在。然而在实际开发中,空指针无处不在,一不小心就会造成陷阱。此外,该计划中还潜伏着一些NPE。它们只有在遇到某些特殊情况时才会出现,并且很难被发现。
那么,我们怎样才能尽量避免NPE的发生呢?总结一下,这里有7件值得收藏的物品!
# 注意:调用方法时记得检查null
这其实是正确的废话!写Java的人都知道,使用对象时可能会出现空指针,所以空指针“最好记住”,但关键是如果你能记住它,NPE就不会那么困难。而且在某些情况下,NPE隐藏得非常深,以至于当真正的问题发生时,它常常被发现。
提高短期判断意识,养成短期判断的直觉和习惯,绝对是最理想的解决方案。但理想很性感,现实很骨感,人又不可靠,所以我们可以用工具来监控我们。
IDEA是一个非常好的帮手。从IDEA的角度来看,上面的代码是这样的:
对于这样的低级错误,IDEA会重点提醒你:这里有NPE,请格外小心!养成阅读警告的习惯比养成判断空头的习惯更容易。
# 等于方法
我们经常需要判断两个对象是否相等(equals)。这个时候我们可以这样做:
public String MaybeNull(String word, String defaultVal) { //不要这样做! if (word.equals("哈哈")) { return defaultVal; } else if (word.equals(defaultVal)) { return "相同" ; } else { 返回"确定"; } }
该方法中,有两个地方容易出现NPE:
word.equals("哈哈")
word.equals(默认值)
对于第一种情况,通常有两种处理方法:
word!=nullword.equals("哈哈")
"哈哈".等于(字)
第二种方法显然更受欢迎。但是,对于两个变量都是变量的word.equals(defaultVal) 比较,第二种方法不适用。你需要这样判断:
if ("哈哈".equals(word)) { return defaultVal; } else if (word !=null word.equals(defaultVal)) { return "相同"; }
想象一下,如果你的方法中有一堆这样的判断,会不会很烦人,会不会很容易分心,错过几个简短的判断?
所以我推荐使用Objects.equals(a,b)方法,这样就不用担心两个对象中是否有空值:
if (Objects.equals("Null", word)) { return defaultVal;} else if (Objects.equals(word, defaultVal)) { return "Same";}
# 自动拆箱陷阱
有一个场景不太好找但是很容易出现NPE:
public boolean isZero(Integer num) { return num==0;}
用这种方法,可能很难一眼就发现问题,正常使用就不会出现问题。直到有一天,你向这个方法传递了一个空值,悲剧发生了。
线程“main”中的异常java.lang.NullPointerException 在com.dadiyang.Computer.isZero(Computer.java:18) 在com.dadiyang.Computer.main(Computer.java:9)
这是自动拆箱机制导致的异常。当进行==比较时,包装类Integer 对象会自动拆箱为int。当Integer对象为空值时,拆箱会抛出NPE。
这种场景下,最好的办法当然是尝试将方法参数改为int:
公共布尔isZero(int num) { return num==0;}
但如果你的方法调用者确实需要处理包装类,那么调用者一定要小心,他们也会遇到自动拆箱的问题:
在这种情况下,您的方法将负责空调用。你也可以写:
公共布尔isZero(Integer num) { return Objects.equals(0, num);}
注意:只有当您明确知道您的方法需要处理包装类时,才使用包装类作为参数。
Objects工具类为我们提供了几个相当不错的静态方法,可以大大降低NPE的概率。除了Objects.equals 方法。
Objects.toString(Object o,String nullDefault)Objects.requireNonNull(T obj,SuppliermessageSupplier)
这也是一个非常实用的方法!
# 判断字符串是否为空
实际上,清空字符串是一个非常频繁的操作。我们不仅需要判断一个字符串是否为null,还需要知道它是否为空字符串,甚至是否为空字符串。
新人常犯的一个错误是刚出现时就直接判断:
if(str.trim().isEmpty())
这就是NPE 发挥作用的地方!在这种情况下,你必须记住str可能为空,所以正确的姿势应该是:
if(str==null||str.trim().isEmpty())
然而,想象一下这种无聊又臭气熏天的判断随处可见。你会一边写一边睡着,然后你就会错过一两个。再说一遍,人都是不可靠的!
事实上commons-lang3为我们提供了一些非常有用的方法。最常用的方法是StringUtils.isEmpty/isBlank(str),用于判断字符串是否为空。不用担心str 为空,只需使用:
if(StringUtils.isBlank(str))
另一种类似的方法是转换字符串大小写:
if(word.equals(str.toLowerCase()))
如果你经常这样写,你肯定会每天被NPE所困扰。对于这样的表达式,如果你思考一下,你可能知道要执行null 测试:
if (word !=null word.equals(str !=null ? str.toLowerCase() : null))
OK,这样写的话,至少不会报空指针了。不过,还是会挖坑的!也许几个月后的某一天,一个你找不到的bug会让你彻夜难眠!只是因为你没有考虑到word和str都是空值的情况。所以正确的写法是:
if (word==null str==null) { return true;} else { String lowerStr=str==null ?第: 章返回单词!=null word.equals(lowerStr);}
好吧,我真的不能再写这么无聊的代码了~~
于是我一挥手,写道:
if (Objects.equals(word, StringUtils.lowerCase(str))){.}
# 检查集合是否为空
与字符串null 测试一样,set null 测试也是一个非常常见的语句:
if(!list.isEmpty()){}
说了这么多,你还这样写,NPE大概爱死你了~
if(list!=null!list.isEmpty()){}
还能更优雅一点吗?当然!
Commons-lang3的好朋友commons-collections为我们提供了一系列针对集合的工具方法,其中就包括清空方法CollectionUtils.isEmpty(list)。因此,更优雅的写法是:
if(CollectionUtils.isNotEmpty(列表)){}
有isEmpty,当然就会有isNotEmpty~
# 编写方法时尽量不要返回空值
我们经常定义一个返回集合的方法,如下所示:
公共ListasList(String[] arr){ if (arr==null) { return null; } }
返回Arrays.asList(arr);}
这样的方法定义当然是没有问题的。但如果调用你方法的人是个大佬,那就太疯狂了。我们做开发的时候,最好有一点用户思维。为了避免给用户(其实是我们自己)带来不必要的麻烦,在编写方法时尽量不要返回空值,特别是当返回值是集合时,可以通过返回空集合来避免空指针。当然,总是new一个空集合也会影响性能,所以我们可以使用:Collections.emptyMap/emptySet/emptyList();返回全局共享的不可变空集合:
公共ListasList(字符串[] arr){
if (arr==null) { return Collections.emptyList(); } }
返回Arrays.asList(arr);}
请注意,Collections.emptyList() 返回一个不可变的空集合。不要尝试向其中添加元素,否则会报错!大多数情况下,我们不可能直接向方法返回的集合中添加元素,所以放心使用即可。
作为来电者,我们需要采取“不信任”的原则。即使这个方法声称不会返回空值,我们在处理返回值时仍然要考虑空值。谁知道,有一天可能有人不小心改变了这个方法,突然返回一个空值~
选修的
Optional是Java8带来的新特性。相当不错,但是相对于其他语言,比如Grovvy或者C#对空指针的处理,我感觉这个Optional实在是太弱了。在Grovvy 和C# 中,有一个.运算符,只需通过str?toString() 即可实现。
str==null?null:str.toString()
效果一样。但不是Java。
不过,Optional毕竟是Java8中引入的解决NPE的强大工具,我们还是需要学习一下。尤其是当Optional与Lambda表达式结合使用时,将会非常强大。详情请参考这篇文章:http://weishu.me/2015/12/08/use-optional-avoid-nullpointexception/
假设我们有这样的代码:
if ("3.0".equals(soundcard.getUSB().getVersion())) { System.out.println("ok");}
显然,这里soundcard和soundcard.getUSB()都可能为空,所以需要进行空测试:
if(声卡!=null){
USB usb=soundcard.getUSB();
if(usb !=null "3.0".equals(usb.getVersion()){ System.out.println("ok"); }}
使用Optional和Lambda表达式,您可以避免这些空计算:
Optional.ofNullable(soundCard) .map(SoundCard:getUsb) .filter(usb -"3.0".equals(usb.getVersion())) .ifPresent((usb) -System.out.println("OK"));
这样,当soundCard 为空或soundCard.getUsb() 为空时,不会发生任何事情。仅当它们都不为空且usb.getVersion() 为3.0 时才会打印OK。
# 总结
1.意识:使用obj.doSomething()时记得判断obj !=null。意识的培养需要一个漫长的过程,我们可以借助工具来帮助。 IDEA 是一个优秀的工具。
2、判断对象是否相等时,使用Objects.equals(a, b)。当然,Objects工具类也为我们提供了toString、requireNonNull等好帮手。
3.自动拆箱陷阱。使用包装类与原始类型进行比较时,要特别注意空指针问题。
4、检查字符串是否为空时,使用commons-lang3包StringUtils提供的isEmpty和isBlank方法。另外,使用lowerCase和upperCase进行字符串转换大小写转换也可以避免空指针。
5、使用commons-collections包的CollectionUtils.isEmpty方法检查集合是否为空
6.如果返回集合的接口需要返回空,则应该返回空集合,而不是null。然而,每次更新一个新集合都会影响性能和不必要的对象创建。使用Collections.emptyList();返回全局共享的不可变空集合。
【面试官揭秘:如何在工作场合预防十亿美元级的NPE错误】相关文章:
用户评论
这确实是个很经典的面试问题,考察的是对大型项目风险意识和解决问题的思路。
有7位网友表示赞同!
感觉这个题目有点吓人,我平时不会去关注具体的金额。
有11位网友表示赞同!
NPE真是个令人印象深刻的案例,从中可以学到很多关于软件开发的安全性和测试的重要性。
有11位网友表示赞同!
面试官想要看你是不是真的了解NPE会引发什么样的后果,以及你采取什么措施来防范类似错误发生。
有5位网友表示赞同!
我相信任何人都难免犯错,关键是能够从错误中吸取教训改进工作方式。
有12位网友表示赞同!
我平时会在代码编写前期就充分考虑到各种异常情况,尽量避免产生潜在的风险因素。
有8位网友表示赞同!
代码审查和单元测试能够有效降低出现类似NPE的问题概率哦!
有12位网友表示赞同!
我觉得面试官想考察的是你的沟通能力和逻辑思维,要能清晰地解释你的想法和解决方案。
有9位网友表示赞同!
平时多多阅读相关技术文档,了解一些常见的错误类型和原因,可以帮助我们更好地防范风险。
有19位网友表示赞同!
这个案例确实很有启发性,让我反思在工作中需要注意哪些细节才能避免潜在的灾难性的后果。
有9位网友表示赞同!
我相信只要态度认真、学习积极,即使犯错也能及时改进,变得更优秀!
有15位网友表示赞同!
面试官想看到你对问题有足够的重视和思考,而不是敷衍了事地回答。
有14位网友表示赞同!
遇到类似问题,我会先冷静分析,找出问题的根源,然后针对性地提出解决方案,并测试方案的效果。
有17位网友表示赞同!
我认为每个程序员都应该学习NPE的相关知识,这不仅关乎程序的安全性,更关系到公司的声誉和用户信赖。
有6位网友表示赞同!
这次的面试题让我意识到,工作不仅仅是完成任务,更是需要对每一项工作认真对待。
有15位网友表示赞同!
我会在代码开发过程中注重细节,并养成良好的习惯,例如及时进行代码审查和单元测试,来降低出现的错误率。
有11位网友表示赞同!
学习NPE的教训,提高我们的编程能力和意识,才能为软件开发行业做出更有价值的贡献!
有17位网友表示赞同!
这次面试题让我看到了自己的不足,我会继续努力学习,提升自己的技术水平和应对问题的能力!
有14位网友表示赞同!