什么是包装类型 在 Java 中,数据类型总共可以分为2大类 : 基础数据类型和引用数据类型。基础数据类型并不支持面向对象编程,因为基础数据类型不具备"对象"的特性 – 携带属性和方法。 所以 Java 为8种基础数据类型提供了对应的类,他们就是包装类,侧面的将基础数据类型变为类,符合面向对象编程。 之所以没有一开始就是提供包装类,不使用基础数据类型,个人认为只是为了迎合人类根深蒂固的习惯,并的确能简单、有效地进行常规数据处理。总的来说:包装类就是基础数据类型在面向对象中的体现。
种类
基本数据类型对应的包装类byte(1字节)Byteshort (2字节)Shortint (4字节)Integerlong (8字节)Longchar (2字节)Characterfloat (4字节)Floatdouble(8字节)Doubleboolean (未定)Boolean在 Java boolean 的大小,有三种说法 1/8字节,1字节,4个字节
Java 代码中的关系在 Java 中,我们可以无缝的在包装类型和基础数据类型之间切换,之间是有一个装换过程的,这个过程就是 装箱/拆箱
// jdk5 之前,我们如果需要将一个基础数据和包装类型切换,需要手动处理 int m = 500; // 手动装箱 Integer obj = new Integer(m); // 手动拆箱 int n = obj.intValue(); // jdk5 后支持自动装箱和拆箱 // 自动装箱,实质是调用 对应包装类.valueOf() 方法实现的 Integer obj = m; // 自动拆箱,实质是调用 对应包装类.xxxValue()方法实现的,其中的xxx 就是对应的数据基础数据类型 int n = obj;从装箱和拆箱,我们可以知道,把一个基础数据类型转为对应的包装类型,有2种方式
// 主动装箱 Integer num = new Integer(1); // 自动装箱 Integer num = 1;这2种方式,虽然都能达到 将一个基础数据类型转为包装类型,但是他们内部的实现,还是有很大的区别,这个区别很多时候,能被用到很多面试题上(亲测,被问过好几次)。
手动装箱 public class Integer { // 内部还是通过一个基础数据类型存储我们的数据值的 private final int value; public Integer(int value) { this.value = value; } }从 Integer 的源码我们可以知道,我们每次手动装箱,都会创建一个新的 Integer 对象。
自动装箱 public class Integer { /** 自动装箱 会调用到这个方法 */ public static Integer valueOf(int i) { // 从这3行的 逻辑和 变量名 我们可以推测出 // 如果我们 装箱的值 Integer缓存的下限 <= i <= Integer缓存的上限,那么他会从 Interger的缓存里面取出对应的包装类,// 否则就重新创建一个新的 // 那么 Integer的上下限分别是多少呢,这个就需要看到 IntegerCache的代码了 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[]; private IntegerCache() {} static { int h = 127; // 读取启动命令行 里面的 java.lang.Integer.IntegerCache.high 配置的值 String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { try { int i = parseInt(integerCacheHighPropValue); // 从配置的值和127中取大的那一个 i = Math.max(i,127); // 控制 h 的值 小于等于 Integer.MAX_VALUE - 129 // 这里说一下,h 和 high 都是 int 声明的,所以最大值为 Integer.MAX_VALUE // 同时为了避免下面的(high - low) + 1 = high + 128 + 1 经过运算后超过了 int 的最大值,变为负数,所以此处才需要控制 h 的最大上限为 Integer.MAX_VALUE - 129 h = Math.min(i,Integer.MAX_VALUE - (-low) -1); } catch( NumberFormatException nfe) { } } high = h; cache = new Integer[(high - low) + 1]; int j = low; // 创建 一个 缓存数组 存放 -128 到 h for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); assert IntegerCache.high >= 127; } } } 从 Integer 的源码 可以知道,Integer 内部维护了一个Integer的缓存,这个缓存默认为 -128 到 127 之间,所以我们通过自动装箱创建的 Integer 并且值在这个区间内,都是从缓存里面获取到的,>2. 同时我们可以在我们程序启动时,指定参数 java.lang.Integer.IntegerCache.high = 你想要设置的缓存上限,修改我们的Integer缓存池的上限几个数值包装类型,除了有精度的 Float 和 Double 外都有对应的缓存,都是 [-128,127] 之间,但是只要 Integer 支持 配置包装类型的知识就这些吧,在判断2个对象是否一样时,基本可以从下面入手
比较的是数值,还是对象,存在自动装箱和自动拆箱比较的是包装类型,是否自动装箱了,值超过了缓存包装类型进行了运算,默认运算后的结果是基础数据类型低精度和高精度运算,低精度换转为高精度Double 和 Float 的自动装箱没有缓存