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.所以直接报空指针异常
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值