IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java:分析三目运算符的执行原理(jdk1.8基于字节码分析装箱拆箱问题) -> 正文阅读

[Java知识库]Java:分析三目运算符的执行原理(jdk1.8基于字节码分析装箱拆箱问题)

当前版本:jdk1.8

1. 声明

当前内容主要为复习三目运算符中的内容,当前思考主要来源于《Java开发手册(泰山版)》灵魂13问书籍中的三目运算,本人由于对其看的不是很懂,所以觉得从字节码方面入手可以解决该问题,顺便归纳总结一下

2. 基本问题出现

public class OperationTest {
	public static void main(String[] args) {
		//test5();
	}
	
	private static void test8() {
		boolean flag = true; 
		boolean simpleBoolean = false; 
		Boolean objectBoolean = true;
		Boolean nullBoolean = null;
		Boolean x6 = flag ? simpleBoolean : nullBoolean;
	}
	
	// 异常
	private static void test7() {
	
		boolean flag = true; 
		boolean simpleBoolean = false; 
		Boolean objectBoolean = true;
		Boolean nullBoolean = null;
		Boolean x6 = flag ? nullBoolean : simpleBoolean;
	}
	
	// 不报错
	private static void test6() {
		boolean flag = false; 
		boolean simpleBoolean = false; 
		Boolean nullBoolean = null;
		Boolean x = flag ?  nullBoolean: simpleBoolean; 
		
	}
	
	private static void test5() {
		boolean flag = false; 
		boolean simpleBoolean = false;
		Boolean nullBoolean = null;
		Boolean x = flag ? simpleBoolean : nullBoolean; 
	}
	
	// 不报错
	private static void test4() {
		boolean flag = true; 
		boolean simpleBoolean = false;
		Boolean nullBoolean = null;
		boolean x = flag ? simpleBoolean : nullBoolean; 
	}
	
	// 异常
	private static void test3() {
		boolean flag = true;
		boolean simpleBoolean = false; 
		Boolean nullBoolean = null;
		boolean x = flag ? nullBoolean : simpleBoolean;
	}
	
	// 报错
	private static void test2() {
		boolean flag = false; 
		boolean simpleBoolean = false; 
		Boolean nullBoolean = null;
		boolean x = flag ? simpleBoolean : nullBoolean; 
	}
	// 不报错
	private static void test1() {
		boolean flag = false; 
		boolean simpleBoolean = false; 
		Boolean nullBoolean = null;
		boolean x = flag ? nullBoolean : simpleBoolean; 
	}

	
}

测试上面的用例得到的结果如下

表达式结果
boolean x = false ? null : false不报错
boolean x = false ? false : null异常
boolean x = true ? null : false异常
boolean x = true ? false : null不报错
Boolean x = false ? false : null异常
Boolean x = false ? null : false不报错
Boolean x = true ? null : false异常
Boolean x = true ? false : null不报错

对于上面的表格可能看起来不是容易理解,所以本人决定使用字节码解析方式得到规律

3.字节码解析和查看并得到总结

private static void test1();
    descriptor: ()V
    flags: ACC_PRIVATE, ACC_STATIC
    Code:
      stack=1, locals=4, args_size=0
         0: iconst_0
         1: istore_0
         2: iconst_0
         3: istore_1
         4: aconst_null
         5: astore_2
         6: iload_0
         7: ifeq          17
        10: aload_2
        11: invokevirtual #28                 // Method java/lang/Boolean.booleanValue:()Z
        14: goto          18
        17: iload_1
        18: istore_3
        19: return

从解析第一个test1可以发现当前只有一个拆箱的操作,并没有其他(可以发现1-4都是最多只有拆箱操作)

private static void test5();
    descriptor: ()V
    flags: ACC_PRIVATE, ACC_STATIC
    Code:
      stack=1, locals=4, args_size=0
         0: iconst_0
         1: istore_0
         2: iconst_0
         3: istore_1
         4: aconst_null
         5: astore_2
         6: iload_0
         7: ifeq          14
        10: iload_1
        11: goto          18
        14: aload_2
        15: invokevirtual #28                 // Method java/lang/Boolean.booleanValue:()Z
        18: invokestatic  #22                 // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
        21: astore_3
        22: return

从test5中可以得到这里一般都会有装箱操作,且可能会有拆箱操作(5-8是基本差不多的)

于是得到汇总图

表达式结果拆装箱
boolean x = false ? null : false不报错((false没有拆箱;true有拆箱操作)
boolean x = false ? false : null异常(false有拆箱操作;true没有拆箱操作)
boolean x = true ? null : false异常(ture有拆箱操作;false没有拆箱操作)
boolean x = true ? false : null不报错(true没有拆箱操作,false才会有拆箱操作)
Boolean x = false ? false : null异常(false导致先拆箱后装箱;true导致进行装箱操作)
Boolean x = false ? null : false不报错(false导致装箱操作;true导致先拆箱后装箱)
Boolean x = true ? null : false异常(true导致先拆箱后装箱;false导致装箱操作)
Boolean x = true ? false : null不报错(true导致装箱操作;false导致先拆箱后装箱)

4. jdk1.8中的总结

1. 当最左边的类型为基本类型的时候,且右边的表达式中存在包装和基本类型时,对于包装类型只会出现拆箱操作

2. 当最左边的类型为包装类型的时候,且右边的表达式中存在包装和基本类型时,对于包装类型进行拆箱然后装箱对于基本类型只会装箱

所以对于以下

Map<String,Boolean> map = new HashMap<String, Boolean>();
Boolean b = (map!=null ? map.get("Hollis") : false);

由于最左边为包装,且flag为true右边存在基本类型和包装类型,且map.get("Hollis") 得到的为包装类型,所以必定会出现先拆箱然后装箱,此时map.get(“Hollis”)为null.所以直接报空指针异常
在这里插入图片描述

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-13 21:36:26  更:2022-03-13 21:40:38 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:41:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码