目录
问题描述
代码
简单分析
-
问题描述
- 在返回一个类型是boolean的方法中,将从map里面取出的Boolean类型的值直接返回,代码一运行,执行到这立即出现了空指针问题(问题一)
- 于是就使用log分析,将字符和Boolean类型的值拼接打印,结果log处居然也出现了空指针问题(问题二)
- 仔细想了想包装类型不就是对象么,取到了空值报异常不是很正常,改了改果然能运行了
-
代码
- 问题一
- 问题二
-
简单分析
- 问题一
- 在第一段代码中,直接返回了stateMap.get(id),这里拿到的值实际是Boolean类型的null值,作为boolean类型返回需要进行拆箱
- 而null值拆箱,问题便不言而喻了
- 而且因为Boolean类型是一个类,所以Boolean类型对象的默认值是null
- 这直接当boolean使用明显不对,包装类型并不能完全代替基本类型
- 稍微修改一下进行解决,如下:
- 问题二
- 前面说到了Boolean类型的值是一个对象,那直接使用字符串拼接不应该拼接出null显示吗?
- 如下:
- 然而实际情况是抛了空指针异常,这又是什么问题?
- 既然是拼接出了问题,首先了解一下字符串拼接的原理
- Java使用 “+” 拼接字符串看起来像操作符重载,实际上并不是
- Java是不支持运算符重载的,这其实只是Java提供的一个语法糖
- 反编译代码后会发现,其实调用的是StringBuilder的append方法,如下:
- 编译,反编译上面的代码:
- 所以,实际上拼接会调用append方法,那看一下append方法:
- 这里有很多重载的方法,其中符合使用的有两个:
- 那到底重载的时候选择哪个方法呢?
- 这里其实很好理解,自动拆箱发生在什么地方?
- 代码执行的时候发生在什么地方?
- 理解清楚了,就知道到底会调用哪个方法了
- 装箱和拆箱是编译器认可的,而不是虚拟机
- 编译器在生成类的字节码时,插入必要的方法调用
- 虚拟机只是执行这些字节码
- 对于装箱和拆箱,实际上打开源码看一下就明白
- 以Boolean为例,装箱就是调用Boolean的valueOf方法选择预置的 TRUE or FALSE 对象(已经创建好的static对象)
- 拆箱就是调用Boolean对象的booleanValue方法返回value
- 所以既然装箱和拆箱是编译器执行的,那毫无疑问,这里肯定是会执行append(boolean b)这个方法了
- 也就是说,Boolean类型的值在拼接时,首先需要调用它的booleanValue()方法完成拆箱
- 然而和第一个问题一样,null对象怎么调用方法,自然抛出了空指针异常