当前位置: 首页 > >

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

发布时间:

2019独角兽企业重金招聘Python工程师标准>>>



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


    public void processData(String dataParam){? ? if(StringUtils.isEmpty(dataParam)){? ? ? ? return;? ? }? ? //代码省略...}

?


但是有一种空指针异常确实非常隐蔽,那就是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



友情链接: 时尚网 总结汇报 幼儿教育 小学教育 初中学习资料网