早期(编译期)优化之java语法糖

本文详细解析了Java中的自动装箱、拆箱机制,通过实例展示了[-128,128)范围内Integer对象的缓存特性以及装箱、拆箱在运算中的应用。还探讨了equals方法和==运算符的区别,并总结了装箱、拆箱的关键点。
摘要由CSDN通过智能技术生成

自动装箱、拆箱。
他们是java语言中使用最多的语法糖。
从如下代码开始说起:

public static void main(String[] args) {
        Integer a = 1;
        Integer b = 2;
        Integer c = 3;
        Integer d = 3;
        Integer e = 321;
        Integer f = 321;
        Long g = 3L;
        Integer h = new Integer(1);
        System.out.println(c == d);//true
        System.out.println(e == f);//false
        System.out.println(c == (a+b));//true
        System.out.println(c.equals(a+b));//true
        System.out.println(g == (a+b));//true
        System.out.println(g.equals(a+b));//false
        System.out.print(a == h); //false
        System.out.println("=========================");
    }
 Integer a = 1;

会被自动装箱成如下

Integer a = Integer.valueOf(1);

再来看看valueOf的源码:

public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

这段代码中使用到的静态常量如下:

		static final int low = -128;
        static final int high;
        static final Integer cache[];
        static {
	        int h = 127;
	        ...
	        high = h;
	        cache = new Integer[(high - low) + 1];
	         int j = low;
	         for(int k = 0; k < cache.length; k++)
	                cache[k] = new Integer(j++);
			 // range [-128, 127] must be interned (JLS7 5.1.7)
	         assert IntegerCache.high >= 127;
        }

1、如果定义了两个Integer类型的变量,他们的值在[-128,128)之间,那么他们会拿已经定义好的缓存中的对象,包装类型==比较的是对象的地址,所以如下返回时true。

System.out.println(c == d);//true

2、对于1中[-128,128)区间外的值,如示例中的321,就会重新创建新的对象,所以如下结果false。

System.out.println(e == f);//false

3、当封装类型和基本类型进行==、+、-、*、/这五种运算时,会将封装类型自动拆箱,所以如下结果true。

System.out.println(c == (a+b));//true

4、看下Integer的equals源码如下,比较两个变量的类型相同且值相同,则true。

public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

如下代码中a+b首先进行拆箱进行计算后,再通过c.equals(Object obj)方法,基本类型通过Object转成封装类型Integer。所以如下true。

System.out.println(c.equals(a+b));//true

5、g是封装类型,a+b是基本类型,封装类型和基本类型进行==时,会自动拆箱成基本类型进行比较,所以如下为true。

System.out.println(g == (a+b));//true

6、看下Long的equals源码如下,比较两个变量的类型相同且值相同,则true,否则返回false。

public boolean equals(Object obj) {
        if (obj instanceof Long) {
            return value == ((Long)obj).longValue();
        }
        return false;
    }

如下代码中a+b首先进行拆箱进行计算后,再通过g.equals(Object obj)方法,基本类型通过Object转成封装类型Integer。所以如下

System.out.println(g.equals(a+b));//false

7、new对象会创建新的对象,Integer a = 1;是直接从常量池的缓存中取对象。所以false。

System.out.print(a == h); //false

总结:
1、相同类型的==比较的话,如果时引用类型,注意比较两个值是否相等,相等的话是否从缓存中引用对象。
2、对于+、-、*、/、==做运算的时候,会进行自动拆箱。
3、equals对于封装类型比较期类型和值,基本类型会被自动装箱。
4、注意new对象和直接定义Integer封装类型的对象不同。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值