一、基本介绍

包装类的作用: Java 语言中,一切都是对象,但是有例外:8 个基本数据类型不是对象,因此在很多时候非常不方便。为此,Java提供为 8 个基本类型提供了对应的包装类:

基本数据类型 包装类
int(4字节) Integer
byte(1字节) Byte
short(2字节) Short
long(8字节) Long
float(4字节) Float
double(8字节) Double
char(2字节) Character
boolean(未定) Boolean
  • 自动装箱 : 当我们把一个基本类型的值( 20),赋值给引用变量时候,系统可以 自动将它“包装”为相应的包装类的实例程序需要对象时,如果给的只是一个基本类型的值,系统会将它自动装箱为包装类的实例达到的效果:有了自动装箱之后,基本类型的值可以当成对象用—— 其实是【假相】 。
  • 自动拆箱: 当我们需要一个基本类型的值时,但实际上传入的包装类的对象。系 统会自动把对象“剥”开,得到它的值。达到的效果:有了自动拆箱之后,包装类的对象可当成基本类型的值 用——其实是【假相】 。

自动装箱 ----- 基本类型的值 → 包装类的实例

自动拆箱 ----- 基本类型的值 ← 包装类的实例

事实上,包装类比基本类型更好用——基本类型能做的事情,包装类也能做。但包装类能做的,基本类型不一定能做,比如要赋一个 null 值。

二、装箱和拆箱是如何实现的

public class Main {public static void main(String[] args) {         Integer i = 10;//装箱int n = i;//拆箱}
}

反编译为:

package com.mao.a_box;public class Test01
{public Test01(){}public static void main(String args[]){Integer i = Integer.valueOf(10);int n = i.intValue();}
}

从反编译得到的字节码内容可以看出,在装箱的时候自动调用的是Integer的valueOf(int)方法。而在拆箱的时候自动调用的是Integer的intValue方法

因此可以用一句话总结装箱和拆箱的实现过程:

  装箱过程是通过调用包装器的valueOf方法实现的,而拆箱过程是通过调用包装器的 xxxValue方法实现的。(xxx代表对应的基本数据类型)

1.Integer

Integer i1=Integer.valueOf(100);
Integer i2=Integer.valueOf(100);
Integer i3=Integer.valueOf(200);
Integer i4=Integer.valueOf(200);System.out.println(i1==i2);     //true
System.out.println(i3==i4);       //false

输出结果表明i1和i2指向的是同一个对象,而i3和i4指向的是不同的对象。此时只需一看源码便知究竟,下面这段代码是Integer的valueOf方法的具体实现:

@HotSpotIntrinsicCandidatepublic static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}/*** Cache to support the object identity semantics of autoboxing for values between* -128 and 127 (inclusive) as required by JLS.** The cache is initialized on first usage.  The size of the cache* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.* During VM initialization, java.lang.Integer.IntegerCache.high property* may be set and saved in the private system properties in the* jdk.internal.misc.VM class.** WARNING: The cache is archived with CDS and reloaded from the shared* archive at runtime. The archived cache (Integer[]) and Integer objects* reside in the closed archive heap regions. Care should be taken when* changing the implementation and the cache array should not be assigned* with new Integer object(s) after initialization.*/private static class IntegerCache {static final int low = -128;static final int high;static final Integer[] cache;static Integer[] archivedCache;static {// high value may be configured by propertyint h = 127;String integerCacheHighPropValue =VM.getSavedProperty("java.lang.Integer.IntegerCache.high");if (integerCacheHighPropValue != null) {try {h = Math.max(parseInt(integerCacheHighPropValue), 127);// Maximum array size is Integer.MAX_VALUEh = Math.min(h, Integer.MAX_VALUE - (-low) -1);} catch( NumberFormatException nfe) {// If the property cannot be parsed into an int, ignore it.}}high = h;// Load IntegerCache.archivedCache from archive, if possibleVM.initializeFromArchive(IntegerCache.class);int size = (high - low) + 1;// Use the archived cache if it exists and is large enoughif (archivedCache == null || size > archivedCache.length) {Integer[] c = new Integer[size];int j = low;for(int i = 0; i < c.length; i++) {c[i] = new Integer(j++);}archivedCache = c;}cache = archivedCache;// range [-128, 127] must be interned (JLS7 5.1.7)assert IntegerCache.high >= 127;}private IntegerCache() {}}

可以发现valueOf(i)函数进入后 i首先和IntegerCache.low以及IntegerCache.high比较,而IntegerCache内部类定义low为-128,high为127.同时声明Cache的大小可以被{@code -XX:AutoBoxCacheMax=}设定,而且cache在第一次使用的时候被初始化。

那么换句话说在使用Integer.valueOf()时,首先就产生了一个值从-128–127的缓存区域,如果要autoBoxing的数字在这个缓存里,就不需要新创建了,直接饮用这里的地址,所以例子中的100可以直接引用,而200需要分别new Integer()。

在通过valueOf方法创建Integer对象的时候,如果数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用否则创建一个新的Integer对象

2.Double

Double i1=Double.valueOf(100);
Double i2=Double.valueOf(100);
Double i3=Double.valueOf(200);
Double i4=Double.valueOf(200);System.out.println(i1==i2);     //false
System.out.println(i3==i4);       //false

为什么Double类的valueOf方法会采用与Integer类的valueOf方法不同的实现。

很简单:在某个范围内的整型数值的个数是有限的,而浮点数却不是

注意,Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。

     Double、Float的valueOf方法的实现是类似的。

可以看一下Double中valueOf()的实现代码:

@HotSpotIntrinsicCandidatepublic static Double valueOf(double d) {return new Double(d);}

发现没有提前初始化缓存区域,而是直接new 新的对象,所以每次产生的都是不一样的对象

3.Boolean

public class Main {public static void main(String[] args) {Boolean i1 = false;Boolean i2 = false;Boolean i3 = true;Boolean i4 = true;System.out.println(i1==i2);System.out.println(i3==i4);}
}
//true
//true

至于为什么是这个结果,同样地,看了Boolean类的源码也会一目了然。下面是Boolean的valueOf方法的具体实现:

public static Boolean valueOf(boolean b) {return (b ? TRUE : FALSE);}

而其中的 TRUE 和FALSE又是什么呢?在Boolean中定义了2个静态成员属性:

public static final Boolean TRUE = new Boolean(true);/** * The <code>Boolean</code> object corresponding to the primitive * value <code>false</code>. */public static final Boolean FALSE = new Boolean(false);

谈谈Integer i = new Integer(xxx)和Integer i =xxx;这两种方式的区别。

  当然,这个题目属于比较宽泛类型的。但是要点一定要答上,我总结一下主要有以下这两点区别:

  1)第一种方式不会触发自动装箱的过程;而第二种方式会触发;

  2)在执行效率和资源占用上的区别。第二种方式的执行效率和资源占用在一般性情况下要优于第一种情况(注意这并不是绝对的)。

下面程序的输出结果是什么?

public class Main {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;Long h = 2L;System.out.println(c==d);System.out.println(e==f);System.out.println(c==(a+b));System.out.println(c.equals(a+b));System.out.println(g==(a+b));System.out.println(g.equals(a+b));System.out.println(g.equals(a+h));}
}
/*true
false
true
true
true
false
true*/

其反编译为:

package com.mao.a_box;import java.io.PrintStream;public class Main
{public Main(){}public static void main(String args[]){Integer a = Integer.valueOf(1);Integer b = Integer.valueOf(2);Integer c = Integer.valueOf(3);Integer d = Integer.valueOf(3);Integer e = Integer.valueOf(321);Integer f = Integer.valueOf(321);Long g = Long.valueOf(3L);Long h = Long.valueOf(2L);System.out.println(c == d);System.out.println(e == f);System.out.println(c.intValue() == a.intValue() + b.intValue());System.out.println(c.equals(Integer.valueOf(a.intValue() + b.intValue())));System.out.println(g.longValue() == (long)(a.intValue() + b.intValue()));System.out.println(g.equals(Integer.valueOf(a.intValue() + b.intValue())));System.out.println(g.equals(Long.valueOf((long)a.intValue() + h.longValue())));}
}

第一个和第二个输出结果没有什么疑问。第三句由于  a+b包含了算术运算,因此会触发自动拆箱过程(会调用intValue方法),因此它们比较的是数值是否相等。而对于c.equals(a+b)会先触发自动拆箱过程,再触发自动装箱过程,也就是说a+b,会先各自调用intValue方法,得到了加法运算后的数值之后,便调用Integer.valueOf方法,再进行equals比较。同理对于后面的也是这样,不过要注意倒数第二个和最后一个输出的结果(如果数值是int类型的,装箱过程调用的是Integer.valueOf;如果是long类型的,装箱调用的Long.valueOf方法)。

Java自动装箱与自动拆箱(包装类)以及Integer和Double的valueOf()源码分析相关推荐

  1. java观察者模式类图_设计模式(十八)——观察者模式(JDK Observable源码分析)...

    1 天气预报项目需求,具体要求以下: 1) 气象站能够将天天测量到的温度,湿度,气压等等以公告的形式发布出去(好比发布到本身的网站或第三方).java 2) 须要设计开放型 API,便于其余第三方也能 ...

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

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

  3. RabbitMQ自动扩展消费者源码分析

    1 前言 在 RabbitMQ异常监控及动态控制队列消费的解决方案 中,提供了一种在线动态修改消费者数量的方法,但使用该方法需要及时的监控队列消息的堆积情况,不能做到自动扩展(增加或减少)消费者数量, ...

  4. 【java基础】包装类,自动装箱和自动拆箱

    文章目录 基本介绍 包装类 自动装箱 自动拆箱 包装类注意事项 包装类比较 包装器内容不可变 基本介绍 有时,需要将int这样的基本类型转换为对象.所有的基本类型都有一个与之对应的类. 例如,Inte ...

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

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

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

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

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

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

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

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

  9. 【自动装箱】Java自动装箱、自动拆箱

    Java中集合只允许存储引用数据类型,那么 int char double等基础数据类型,如何存储在集合里呢?Java在JDK1.5版本以后推出了自动装箱.自动拆箱操作,那么什么是自动装箱呢,下面我们 ...

  10. java中为什么自动装箱拆箱_Java自动装箱和自动拆箱的理解

    Java自动装箱和自动拆箱的理解 1.代码 public class AutoBoxing { public static void main(String[] args) { Integer a = ...

最新文章

  1. YOLOV4知识点分析(二)
  2. C语言程序可以没有main函数
  3. 卸载LINUX自带的JDK——linux-jdk-java
  4. 汇编-debug结果正确与执行结果错误
  5. spacy 报错 gold.pyx in spacy.gold.GoldParse.__init__() 解决方案
  6. 沈南鹏问了微软CEO四个问题
  7. 深度学习论文阅读进阶路径图
  8. python串口通信_python 读取串口数据的示例
  9. 3dmax导出fbx ue4_耗子尾汁马保国—CC3快速相片建模到UE4实时面部,动作捕捉
  10. Bag-of-words模型-可用于计算文本及图片相似度
  11. 小学期实践心得(1)
  12. python模板代码替换_Python - 安全替换字符串模板(safe_substitute) 详细解释
  13. Python中的闭包与参数引用域
  14. c语言中整型实型是什么,C语言中为何整型变量以实型变量输出为0?
  15. 关于电平转换电路1.8V转3.3V
  16. 逆向分析系列——查壳侦壳工具
  17. Linux定时器alarm()用法讲解
  18. 01-SNAP与snappy介绍及安装
  19. HDU 1425 sort
  20. Comet OJ - 2019国庆欢乐赛 G 后缀数组

热门文章

  1. 在Linux中,如何找回root密码(So easy!!)
  2. 个人永久性免费-Excel催化剂功能第29波-追加中国特色的中文相关自定义函数
  3. 未来十年最容易消失和最不易被取代的22个职业,越看越心惊!附相关专业
  4. scandef格式详细说明
  5. 气血瘀滞热入血室闭经案
  6. 中国科学技术大学计算机考研好考吗,中国科学技术大学计算机考研复习方法谈(2)...
  7. 计算机桌面上的声音图标没了,Windows7旗舰版桌面音量图标消失的原因
  8. cdn刷新api_阿里云cdn刷新api
  9. nova青春版支持鸿蒙吗,华为nova青春版评测:高颜值年轻人必备
  10. Linux C++编译及 静态/动态 链接库 笔记