关于Integer的自动装箱与自动拆箱

自动装箱

Integer x1 = 36和Integer n1 = new Integer(36)有什么区别?我们尝试运行下面代码看看会是什么结果:

public class Int {public static void main(String[] args) {Integer x1 = 36;Integer x2 = 36;boolean r1 = x1==x2;System.out.println("x1==x2:" + r1);Integer y1 = 360;Integer y2 = 360;boolean r2 = y1==y2;System.out.println("y1==y2:" + r2);Integer n1 = new Integer(36);Integer n2 = new Integer(36);boolean r3 = n1==n2;System.out.println("n1==n2:" + r3);Integer m1 = new Integer(360);Integer m2 = new Integer(360);boolean r4 = m1==m2;System.out.println("m1==m2:" + r4);}
}

运行结果:

x1==x2:true
y1==y2:false
n1==n2:false
m1==m2:false

看到运行结果是不是感觉有些奇怪,y1 == y2、n1 == n2、m1 == m2为什么结果是false?我们对代码进行反编译,反编译后代码如下:

public class Int {public static void main(String[] args) {Integer x1 = Integer.valueOf(36);Integer x2 = Integer.valueOf(36);boolean r1 = (x1 == x2);System.out.println("x1==x2:" + r1);Integer y1 = Integer.valueOf(360);Integer y2 = Integer.valueOf(360);boolean r2 = (y1 == y2);System.out.println("y1==y2:" + r2);Integer n1 = new Integer(36);Integer n2 = new Integer(36);boolean r3 = (n1 == n2);System.out.println("n1==n2:" + r3);Integer m1 = new Integer(360);Integer m2 = new Integer(360);boolean r4 = (m1 == m2);System.out.println("m1==m2:" + r4);}
}

从反编译结果来看,Integer x1 = 36和Integer n1 = new Integer(36)分别调用了Integer.valueOf(int i)和Integer(int value)方法。Integer.valueOf(int i)和Integer(int value)源码如下:

public Integer(int value) {this.value = value;
}public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);
}private static class IntegerCache {static final int low = -128;static final int high;static final Integer cache[];static {// high value may be configured by propertyint h = 127;String integerCacheHighPropValue =sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");if (integerCacheHighPropValue != null) {try {int i = parseInt(integerCacheHighPropValue);i = Math.max(i, 127);// Maximum array size is Integer.MAX_VALUEh = Math.min(i, Integer.MAX_VALUE - (-low) -1);} catch( NumberFormatException nfe) {// If the property cannot be parsed into an int, ignore it.}}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;}private IntegerCache() {}
}

Integer是int类型的包装类,当int值赋值给Integer时会使用valueOf(int i)方法自动装箱。从源码可以看出,默认情况下cache[]缓存范围是[-128,127]。对于valueOf(int i),当i在[-128,127]内,则直接返回catch中缓存的Integer对象,所以,x1,x2其实指向了同一个Integer对象。当i在[-128,127]外,则会重新new一个Integer对象并且返回,所以y1,y2其实是指向了不同的Integer对象。new Integer(36)和new Integer(360)调用Integer构造函数,得到的是不同的Integer对象。由此可见它们的不同之处是:x1、x2指向了同一个Integer对象,y1、y2、n1、n2、m1、m2各指向不同的Integer对象。对于对象引用类型:“ == ”比较的是对象的内存地址,对于基本数据类型比较的是数值。所以x1 == x2结果为true,y1 == y2、n1 == n2、m1 == m2结果为false。

自动拆箱

我们在运行一下下面代码:

Unpacking.java

public class Unpacking {public static void main(String[] args) {int a = 10;Integer b = 10;boolean result = a == b;System.out.println(result);}
}

运行结果:

true

我们对代码进行反编译,反编译后代码如下:

public class Unpacking {public static void main(String[] args) {int a = 10;Integer b = Integer.valueOf(10);boolean result = (a == b.intValue());System.out.println(result);}
}/*** Returns the value of this {@code Integer} as an* {@code int}.*/
public int intValue() {return value;
}

我们看到a、b在比较的时候,b调用了intValue()方法,获取了对象b的value值。这里b调用了intValue()方法进行自动拆箱,将自己的value值与a作比较,结果为true。到这里我们就应该知道,Integer的自动装箱是使用valueOf(int i)方法,自动拆箱是使用intValue()方法。

“==”比较的到底是什么?

前面提到:对于对象引用类型:“==”比较的是对象的内存地址,对于基本数据类型比较的是数值。我们可以通过字节码来证明这一点:

Int.class

//Integer x1 = 36;
//Integer x2 = 36;
//boolean r1 = x1==x2;
//System.out.println("x1==x2:" + r1);0: bipush        36
2: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
5: astore_1
6: bipush        36
8: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
11: astore_2
12: aload_1
13: aload_2
14: if_acmpne     21
17: iconst_1
18: goto          22
21: iconst_0
22: istore_3

在Int类中x1、x2为引用类型。x1==x2比较使用到的是if_acmpne指令,其中a代表 reference的地址(address),是两个引用的比较,点击查看完整字节码。

Test.java

public class Test {public static void main(String[] args) {int a = 3;int b = 4;boolean result = a == b;System.out.println(result);}
}

Test.class

//int a = 3;
//int b = 4;
//boolean result = a == b;0: iconst_3
1: istore_1
2: iconst_4
3: istore_2
4: iload_1
5: iload_2
6: if_icmpne     13
9: iconst_1
10: goto          14
13: iconst_0
14: istore_3

在Test类中x1、x2为基本数据类型。x1 == x2比较使用到的是if_icmpne指令,其中i 代表对 int,是两个数值的比较。所以,对于对象引用类型:“==”比较的是对象的内存地址,对于基本数据类型比较的是数值的结论是对的。

Integer.eqauls()方法

当我们比较两个Integer,想让它们的value相等就返回true时,我们可以使用Integer的equals方法,方法源码如下:

/*** Compares this object to the specified object.  The result is* {@code true} if and only if the argument is not* {@code null} and is an {@code Integer} object that* contains the same {@code int} value as this object.** @param   obj   the object to compare with.* @return  {@code true} if the objects are the same;*          {@code false} otherwise.*/
public boolean equals(Object obj) {if (obj instanceof Integer) {return value == ((Integer)obj).intValue();}return false;
}public int intValue() {return value;
}

Java虚拟机指令集《Java Virtual Machine Specification》Chapter 6. The Java Virtual Machine Instruction Set

关于Integer的自动装箱与自动拆箱相关推荐

  1. Java 进阶——自动装箱和自动拆箱

    1.什么是自动装箱拆箱 基本数据类型的自动装箱(autoboxing).拆箱(unboxing)是自J2SE 5.0开始提供的功能. 一般我们要创建一个类的对象实例的时候,我们会这样: Class a ...

  2. java 自动装箱自动拆箱_自动装箱和自动拆箱

    自动装箱和自动拆箱 Java 提供了 8 种基本数据类型,每种数据类型都有其对应的包装类型,包装类是面向对象的类,是一种高级的数据类型,可以进行一些比较复杂的操作,它们是引用类型而不再基本类型了. 基 ...

  3. 自动装箱与自动拆箱的一些问题

    今天打算复习一下Java基础,之前学的太快速了,现在暑假,好好把那些细节看一下 复习到自动装箱和自动拆箱的时候,这里有个很有趣的现象 Integer n1 = 100; Integer n2 = 10 ...

  4. Java的自动装箱与自动拆箱

    一:什么是自动装箱拆箱 装箱就是自动将基本数据类型转换为包装器类型: 拆箱就是自动将包装器类型转换为基本数据类型. java中需要装箱拆箱的类型如下: 基本数据类型 包装器类型 int(4字节) In ...

  5. 第三次学JAVA再学不好就吃翔(part64)--自动装箱和自动拆箱

    学习笔记,仅供参考 自动装箱和自动拆箱 装箱:把基本类型转换为包装类类型 int x = 100; Integer i1 = new Integer(x); 拆箱:把包装类类型转换为基本类型 int ...

  6. java 自动装箱自动拆箱,java自动装箱、自动拆箱和正常情况性能比较

    自动装箱和自动拆箱是java5.0版本引入的,能自动将基本类型转换为对应的基本类型包装对象,那么我们比较一下他们的性能情况. package com.wmmad.test; import junit. ...

  7. 包装类,包装类的自动装箱和自动拆箱

    目标 1)包装类的作用, 2)掌握包装类的自动装箱和自动拆箱操作. 3)掌握包装类的转换操作. 具体内容 一切皆对象,八种基本数据类型不是对象. 把Int包装成一个类,这样的一个类就可以以对象的形式操 ...

  8. 深入理解自动装箱和自动拆箱

    一.什么是自动装箱.自动拆箱 此机制开始于jdk 1.5 java中有8种基本类型,对应8种基本类型有8个包装类. 整形 实型 布尔型 字符型 long/int/short/byte float/do ...

  9. 装箱和拆箱,自动装箱和自动拆箱

    装箱和拆箱,自动装箱和自动拆箱 以Integer的创建为例. 装箱和拆箱 装箱:把基本数据类型转换成包装类对象(int->Integer) Integer num1=new Integer(17 ...

最新文章

  1. 敏捷开发日常跟进系列之二:燃尽图(中)
  2. Spring Cloud微服务实战:手把手带你整合eurekazuulfeignhystrix
  3. JavaScript 技术篇-chrome浏览器读取剪切板命令document.execCommand(‘paste‘)返回false原因及解决方法
  4. 软件架构乱弹——问题域及其解决方法
  5. pom.xml配置详解
  6. java 比较源文件_Beyond Compare比较Java源代码文件的操作方法
  7. 动态规划——看似dp的贪心问题最大乘积(蓝桥杯试题集)
  8. react-redux草稿
  9. 中国机器自动化控制器行业市场供需与战略研究报告
  10. .NET dnSpy 程序集编辑器,反编译器和调试器
  11. 公司设备损坏了,怎么处理
  12. python电力系统暂态分析_电力系统暂态计算——时域仿真方法
  13. VMWARE 之 分布式网络交换机
  14. C# 多文件压缩与解压
  15. 如何提高自制力?自制力差怎么办?
  16. 计算机03年word做母亲节贺卡,怎样制作母亲节贺卡
  17. ubuntu安装git失败解决办法
  18. 基本概念:线与逻辑、锁存器、缓冲器、建立时间、缓冲时间
  19. 使用runOnUiThread更新UI
  20. 积木拼图游戏-积木游戏世界中文版

热门文章

  1. Java多线程及线程池
  2. 激光SLAM入门学习笔记
  3. java 沙箱_java沙箱绕过
  4. 你就是孩子最好的玩具——情感引导式教育
  5. 基于STM32安装Stm32CubeMX,配合Keil完成LED流水灯和USART串口通讯程序,及其管脚的时序波形观察
  6. python 两个集合做补集
  7. FIL未来走势分析,把握100U关键点位!市场无情,反复操作是深渊危机
  8. MySQL 获取当前时间
  9. 16 个超级实用的 Java 工具类
  10. Google总部员工腐败生活(最新)