一. 🦁 前言
整型、char类型所对应的包装类,在自动装箱时,对于-128~127之间的值会进行缓存处理,其目的是提高效率。
缓存处理的原理为:如果数据在-128~127这个区间,那么在类加载时就已经为该区间的每个数值创建了对象,并将这256个对象存放到一个名为cache的数组中。每当自动装箱过程发生时(或者手动调用valueOf()时),就会先判断数据是否在该区间,如果在则直接获取数组中对应的包装类对象的引用,如果不在该区间,则会通过new调用包装类的构造方法来创建对象。
二. 🦁 源码分析
1. valueOf(int i)
@HotSpotIntrinsicCandidate
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
通过源码我们可知道,当参数i不在[IntegerCache.low , IntegerCache.high]范围内时,就直接实例化一个Integer对象并返回;否则返回IntegerCache类里面的cache数组里面的数据。
那么到这里,我们就能根据语义想得到了,Integer自动拆箱的缓存工作是由IntegerCache类完成的,咱们来点击查看一下这个类的工作原理。
2. IntegerCache类
我们查看这个类时,发现这个类是Integer的静态内部类,且定义了一个静态代码块,如下
/**
* 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.
*/
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
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_VALUE
h = 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() {}
}
这个静态内部类包含了三个变量:low,high,cache[]数组。
- 在静态代码块中,先通过VM.getSavedProperty()来获取high的值,检查"integerCacheHighPropValue"变量是否不为空,如果不为空,它尝试使用parseInt()方法将其解析为整数。如果解析成功,它将"i"的值设置为解析后的整数,并将其与127取最大值。然后它计算"h"变量的最大值,即"i"和Integer.MAX_VALUE减去负的"low"值再减1之间的较小值
如果未设置属性值或无法将其解析为整数,则代码会优雅地忽略该属性,并继续使用默认值 127。
tips:
在Java中,系统属性是提供有关Java虚拟机(JVM)和运行环境配置信息的键值对。可以使用 System.getProperty() 方法访问它们。VM.getSavedProperty()则是类似于 System.getProperty() 方法,可以获取java.lang.Integer.IntegerCache.high
的属性值
- 实例化cache数组的大小为 256,并且循环赋范围为[-128,127]的值进数组中。最后检查是否缓存全部的值(assert IntegerCache.high >= 127)。
- 最后构造私有的构造方法,以防止外部的类访问到IntegerCache。
三. 🦁 总结
Integer是Java语言中的一种基本数据类型,用来表示整数值。其原理是采用二进制补码表示法,即将整数的绝对值转化为二进制数,然后在最高位上添加一个符号位(0表示正数,1表示负数),并将二进制数按位取反,再加上1,得到补码。
例如,十进制数5的二进制表示为101,加上符号位后为0101,取反得到1010,加上1后得到1011,这就是5的补码表示。同理,-5的补码表示为1101。
在计算机内部,整数的加减乘除运算都是在二进制补码的基础上进行的。加法运算时,先将两个数的补码相加,然后对结果进行溢出检查;减法运算时,将被减数的补码取反后再加上减数的补码,即转化为加法运算;乘法运算和除法运算也是在二进制补码的基础上进行的。
总之,Integer数据类型的原理就是采取二进制补码表示法,使得整数的加减乘除运算都能在计算机内部高效地进行。文章来源:https://www.toymoban.com/news/detail-498071.html
这一期的Java基础复习到这里,咱们下一期见!!!文章来源地址https://www.toymoban.com/news/detail-498071.html
到了这里,关于【Integer】| 深度剥析包装类缓存原理Ⅶ的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!