一种隐式的java空指针异常--自动拆箱

在java开发中,我们遇到最多的异常莫过于java.lang.NullPointerException异常了。这个异常我们做好防卫性校验基本就可以避免,比如类似下面

  1. public void processData(String dataParam){
  2.     if(StringUtils.isEmpty(dataParam)){
  3.         return;
  4.     }
  5.     //代码省略...
  6. }

 

但是有一种空指针异常确实非常隐蔽,那就是java的自动拆箱。说道拆箱必须先从装箱开始说起。

java语言有7中数值类型(还有一个布尔类型,一共8个基本类型),下图是它们的数值类型合法转换图:

6个实心箭头表示无信息丢失的转换,有3个虚箭头,表示可能有精度损失的转换。那么我们为什么还需要包装类型呢,8种基本类型分别对应8中包装类型(基本数据类型是在栈中直接分配内存,而包装类型是数据的引用在栈中,但它的对象在堆中,基本类型和包装类型之间的性能比较不在本文论述之内),如下。


上面说了很多铺垫,回到我们的题目上面来,现在我们看下面代码,空指针如何报出来的
java语言是一个面向对象的语言,但是我们在使用基本类型的时候如何面向对象呢,在实际使用中有许多不方便的地方,比如我们在jdk1.5之前java集合是不能放基本类型的。为了解决这方面的不足,就设计了一个包装类,分别与基本类型想对应。在《深入理解java虚拟机》一书第2版,在第10章 “早期(编译期)优化“这章中对装箱和拆箱有语法糖的描述,糖是甜甜的味道,语法糖嘛,就是让这种语法增强功能,^_^。

方法:Long getVenderIdByOrderId(long var1)
line 103:long id = orderService.getVenderIdByOrderId(45767004381L);

java.lang.NullPointerException

line 103能报空指针的地方,一眼能够看出的两点:参数为空和orderService为空,现在明确告知,这两个都不为空,但是这行代码还是报出来空指针,没错,自动拆箱下潜藏了隐式的空指针错误。因为getVenderIdByOrderId返回的是Long,在赋值给id的时候,如果对方接口返回的是null,Long-->long。见下面转换关系,当obj空的时候,必然就有了java.lang.NullPointerException

基本类型------>包装器类
Long obj=new Long(10L);

包装器类------>基本类型
long num=obj.longValue();

我们在单独学习这种基本语法的时候,心里一般都会明白的很,当发生在实际应用中的时候,却经常被忽略掉这种隐式的空指针异常。

另外,还有一些自动装箱的陷阱,比如下面这段代码,结果可以输出看看。

public static void man(String[] args){
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;

System.out.println(c == d);
System.out.println(c == (a+b));
System.out.println(c.equals((a+b)));
}

包装类的”==“运算符在没有遇到算术运算符的情况下不会自动拆箱,还有equals()方法不处理数据转换的关系。所以我们尽量避免这样的使用。

转载于:https://my.oschina.net/wangxindong/blog/799590

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值