网站首页 > java教程 正文
近期一直在刷算法,原创文章写的也比较少,今天的主题不算是一个很大的问题,是我做题的时候出来的,而且还曾在A厂的公众号上看到过,今天自己整理一下,避免大家入坑。
这个问题是三元表达式会在计算的时候出现拆箱的运算,造成空指针异常。
一、问题重现
代码很简单,a是包装类型Integer,初始值是null,b通过三元表达式进行赋值。运行一下这个代码就会出现空指针异常:
为什么会出现这个现象呢?下面我们来分析一下:
二、问题分析
刚刚这个空指针现象很容易我们就想到类型转化上,三元表达式的类型转换同样要遵守一定的规则才可以。
1、三元操作符类型的转换规则:
(1)若两个操作数不可转换,则不做转换,返回值为Object类型
比如Object b = flag ? A : B,此时A和B是两个不同的对象,不可转换,那就把最终结果赋值给Object
(2)若两个操作数是明确类型的表达式(比如变量),则按照正常的二进制数字来转换,int类型转换为long类型,long类型转换为float类型等。
这个就比较容易理解了,比如float b = flag ? 1:1.0f。1为int类型向上转即可。
(3)若两个操作数中有一个是数字S,另外一个是表达式,且其类型标示为T,那么,若数字S在T的范围内,则转换为T类型;若S超出了T类型的范围,则T转换为S类型。
这种情况就是刚刚我们所演示的例子,Integer b = flag ? 1 *2: a,结果是b=a,但是a是null,要强制转换成Integer(1 * 2的类型),于是就出现了空指针。
(4)若两个操作数都是直接量数字,则返回值类型为范围较大者。
这种情况和第二种类似。
现在答案基本上出来了,出现空指针的原因是,a=null,要强制转换Integer,于是出现了空指针,因为虚拟机看到一个null就找不到要转化的对象了。
2、反编译分析
现在我们找到Test的字节码文件,输入javap -c命令,反编译一下:
答案现在应该清楚了,
3、为什么要拆箱(重点)
为什么要对a进行拆箱,直接把a=null赋值给b不就完事了嘛。这一点就需要我们注意一下那个前提条件,也就是说一个是数字,一个是表达式,刚刚的那个例子也验证了这个观点,现在我不是表达式,再来验证一下:
现在我们可以看到不是表达式,依然会出现这个错误。别着急,还有让你更晕的,我们再来改变一下代码:
这尼玛恶心,我测试了很多不同的案例,基本上就分为这两种情况。原因如下:
条件表达式?表达式 1 :表达式 2,假设结果是表达式2
(1)表达式1和2都为null,表达式2看到1是null,则不会进行拆箱。
(2)表达式1为数字或者是表达式,表达式2根据1的类型进行拆箱。
也就是说表达式2主要依据表达式1判断是否进行拆箱操作。
三、问题解决
解决方案很简单,那就是只要遇见null在三元表达式里,就尽量转化为if结构。
猜你喜欢
- 2024-10-26 【基础模块】java运算符,其他语言通用
- 2024-10-26 C/C++编程知识:运算符(七)丨三元/三目运算符知识详解
- 2024-10-26 Java运算符优先级(java运算符优先级别排序正确的是)
- 2024-10-26 JavaScript运算符_三元运算符(十)
- 2024-10-26 Java语言的基本运算符--干货分享(java中常用的运算符有哪几类)
- 2024-10-26 《Java编程思想》第五版:第四章 运算符
- 2024-10-26 Java编程从零开始03 Java的运算符
- 2024-10-26 Java运算符(JAVA运算符的优先级顺序是什么)
- 2024-10-26 大数据 java语法之语法(14)之条件运算符和连接符
- 2024-10-26 Java高质量代码建议1:三元操作符的类型务必一致
你 发表评论:
欢迎- 最近发表
-
- Java常量定义防暴指南:从"杀马特"到"高富帅"的华丽转身
- Java接口设计原则与实践:优雅编程的艺术
- java 包管理、访问修饰符、static/final关键字
- Java工程师的代码规范与最佳实践:优雅代码的艺术
- 编写一个java程序(编写一个Java程序计算并输出1到n的阶乘)
- Mycat的搭建以及配置与启动(mycat部署)
- Weblogic 安装 -“不是有效的 JDK Java 主目录”解决办法
- SpringBoot打包部署解析:jar包的生成和结构
- 《Servlet》第05节:创建第一个Servlet程序(HelloSevlet)
- 你认为最简单的单例模式,东西还挺多
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)