面试官揭秘:如何在工作场合预防十亿美元级的NPE错误

更新:10-29 民间故事 我要投稿 纠错 投诉

大家好,关于面试官揭秘:如何在工作场合预防十亿美元级的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();返回全局共享的不可变空集合。

用户评论

遗憾最汹涌

这确实是个很经典的面试问题,考察的是对大型项目风险意识和解决问题的思路。

    有7位网友表示赞同!

拉扯

感觉这个题目有点吓人,我平时不会去关注具体的金额。

    有11位网友表示赞同!

我怕疼别碰我伤口

NPE真是个令人印象深刻的案例,从中可以学到很多关于软件开发的安全性和测试的重要性。

    有11位网友表示赞同!

。婞褔vīp

面试官想要看你是不是真的了解NPE会引发什么样的后果,以及你采取什么措施来防范类似错误发生。

    有5位网友表示赞同!

〆mè村姑

我相信任何人都难免犯错,关键是能够从错误中吸取教训改进工作方式。

    有12位网友表示赞同!

凉城°

我平时会在代码编写前期就充分考虑到各种异常情况,尽量避免产生潜在的风险因素。

    有8位网友表示赞同!

留我一人

代码审查和单元测试能够有效降低出现类似NPE的问题概率哦!

    有12位网友表示赞同!

放血

我觉得面试官想考察的是你的沟通能力和逻辑思维,要能清晰地解释你的想法和解决方案。

    有9位网友表示赞同!

寻鱼水之欢

平时多多阅读相关技术文档,了解一些常见的错误类型和原因,可以帮助我们更好地防范风险。

    有19位网友表示赞同!

岁岁年年

这个案例确实很有启发性,让我反思在工作中需要注意哪些细节才能避免潜在的灾难性的后果。

    有9位网友表示赞同!

身影

我相信只要态度认真、学习积极,即使犯错也能及时改进,变得更优秀!

    有15位网友表示赞同!

一生荒唐

面试官想看到你对问题有足够的重视和思考,而不是敷衍了事地回答。

    有14位网友表示赞同!

£烟消云散

遇到类似问题,我会先冷静分析,找出问题的根源,然后针对性地提出解决方案,并测试方案的效果。

    有17位网友表示赞同!

轨迹!

我认为每个程序员都应该学习NPE的相关知识,这不仅关乎程序的安全性,更关系到公司的声誉和用户信赖。

    有6位网友表示赞同!

oО清风挽发oО

这次的面试题让我意识到,工作不仅仅是完成任务,更是需要对每一项工作认真对待。

    有15位网友表示赞同!

妄灸

我会在代码开发过程中注重细节,并养成良好的习惯,例如及时进行代码审查和单元测试,来降低出现的错误率。

    有11位网友表示赞同!

在哪跌倒こ就在哪躺下

学习NPE的教训,提高我们的编程能力和意识,才能为软件开发行业做出更有价值的贡献!

    有17位网友表示赞同!

怀念·最初

这次面试题让我看到了自己的不足,我会继续努力学习,提升自己的技术水平和应对问题的能力!

    有14位网友表示赞同!

【面试官揭秘:如何在工作场合预防十亿美元级的NPE错误】相关文章:

1.动物故事精选:寓教于乐的儿童故事宝库

2.《寓教于乐:精选动物故事助力儿童成长》

3.探索动物旅行的奇幻冒险:专为儿童打造的童话故事

4.《趣味动物刷牙小故事》

5.探索坚韧之旅:小蜗牛的勇敢冒险

6.传统风味烤小猪,美食探索之旅

7.探索奇幻故事:大熊的精彩篇章

8.狮子与猫咪的奇妙邂逅:一场跨界的友谊故事

9.揭秘情感的力量:如何影响我们的生活与决策

10.跨越两岸:探索彼此的独特世界

上一篇:《爱恨交织:永恒之恋的终结之谜》 下一篇:宝宝常见皮肤病预防及治疗指南