Java Integer 缓存特性(Integer最大/小值探究整型的自动装箱)
Posted 流楚丶格念
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java Integer 缓存特性(Integer最大/小值探究整型的自动装箱)相关的知识,希望对你有一定的参考价值。
文章目录
问题引出
Integer最大/小值
java中Integer是有最大值和最小值的
最大值为
Integer.MAX_VALUE = 2147483647
最小值为
Integer.MIN_VALUE = -2147483648
注意:两个值并没有互为相反数
有
Integer.MAX_VALUE + 1 = Integer.MIN_VALUE
同理
Integer.MIN_VALUE - 1 = Integer.MAX_VALUE
Integer最大/小值案例
但是用到了这样的一个案例:
public static void test()
//true
Integer a1 = 127, b1 = 127;
System.out.println(a1 == b1);
//false
Integer a2 = new Integer(127);
Integer b2 = new Integer(127);
System.out.println(a2 == b2);
//false
Integer a3 = 128, b3 = 128;
System.out.println(a3 == b3);
//true
Integer a4 = 128, b4 = 128;
System.out.println(a4.equals(b4));
public static void main(String[] args)
test();
比较答案:
true
false
false
true
结果原因
-
第一个使用"
==
"判断 Integer a1 = 127 和 Integer b1 = 127
相等原因:Integer的取值范围是-128~127 -
第二个使用"
==
"判断Integer a2 = new Integer(127) 和 Integer b2 = new Integer(127)
不相等原因:装箱时,java为了提高效率,IntegerCache类中有一个数组将-128<=i<=127范围之内的数据打包成缓存里的Integer对象了,因此不用new,这个区间里的值用直接=赋值方法得到的变量地址就是同一个,而超出这个范围的数值就会new一个Integer对象出来 -
第三个使用"
==
"判断Integer a3=128 和 Integer b3 = 128
不相等原因:因为Integer类型赋值范围在-128—127之间,超出这个范围的数值就会重新new一个Integer对象出来,直接用==去比较是比较a3和b3的地址,a3和b3的地址是不相等的 -
第四个使用使用"
==
"equals()方法判断Integer a4=128 和 Integerb4 = 128
相等原因:使用equals()方法比较的是a4和b4的数值
注意点:"==
"可以用于原始值进行比较,也可以用于对象进行比较,当用于对象与对象之间比较时,比较的不是对象代表的值,而是检查两个对象是否是同一对象,这个比较过程中没有自动装箱发生。进行对象值比较不应该使用”==“,而应该使用对象对应的equals方法。
小总结
JVM会自动维护八种基本类型的常量池,int常量池中初始化-128~127的范围,所以当为Integer i=127时,在自动装箱过程中是取自常量池中的数值,而当Integer i=128时,128不在常量池范围内,所以在自动装箱过程中需new 128,所以地址不一样。
上面就用到了Java自动装箱的概念,下面我们来深入了解一下:
Integer 自动装箱
IntegerCache缓存
Integer 缓存是 Java 5 中引入的一个有助于节省内存、提高性能的特性。
Integer中有个静态内部类IntegerCache,里面有个cache[],也就是Integer常量池,常量池的大小为一个字节(-128~127)。JDK源码如下(摘自JDK1.8源码):
/**
* 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 -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
* sun.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 =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null)
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low));
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
private IntegerCache()
当创建Integer对象时,不使用new Integer(int i)
语句,大小在-128~127之间,对象存放在Integer常量池中。
例如:Integer a = 10;
调用的是Integer.valueOf()
方法,代码为:
public static Integer valueOf(int i)
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
这也是自动装箱的代码实现。
Java自动装箱
JAVA将基本类型自动转换为包装类的过程称为自动装箱(autoboxing)。
实际上在 Java 5 中引入这个特性的时候,范围是固定的 -128 至 +127。后来在Java 6 后,最大值映射到 java.lang.Integer.IntegerCache.high,可以使用 JVM 的启动参数设置最大值。(通过 JVM 的启动参数 -XX:AutoBoxCacheMax=size 修改)
缓存通过一个 for 循环实现。从小到大的创建尽可能多的整数并存储在一个名为 cache 的整数数组中。这个缓存会在 Integer 类第一次被使用的时候被初始化出来。以后,就可以使用缓存中包含的实例对象,而不是创建一个新的实例(在自动装箱的情况下)。
测试情况:
int i = 10;
int i1 = 10;
Integer in1 = 10;
Integer in2 = 10;
Integer in3 = new Integer(10);
Integer in4 = new Integer(10);
Integer in5 = 199;
Integer in6 = 199;
System.out.println(i == i1); // true
System.out.println(i == in1); // true
System.out.println(i == in2); // true
System.out.println(i == in3); // true
System.out.println(in1 == in2); // true
System.out.println(in5 == in6); // false
System.out.println(in1 == in3); // false
System.out.println(in3 == in4); // false
在 Boxing Conversion 部分的Java语言规范(JLS)规定如下:
如果一个变量 p 的值属于:-128至127之间的整数(§3.10.1),true 和 false的布尔值 (§3.10.3),’u0000′ 至 ‘u007f’ 之间的字符(§3.10.4)中时,将 p 包装成 a 和 b 两个对象时,可以直接使用 a ==
b 判断 a 和 b 的值是否相等。
所有整数类型的类都有类似的缓存机制:
- 有 ByteCache 用于缓存 Byte 对象
- 有 ShortCache 用于缓存 Short 对象
- 有 LongCache 用于缓存 Long 对象
Byte,Short,Long 的缓存池范围默认都是: -128 到 127。可以看出,Byte的所有值都在缓存区中,用它生成的相同值对象都是相等的。
所有整型(Byte,Short,Long)的比较规律与Integer是一样的。
同时Character 对象也有CharacterCache 缓存 池,范围是 0 到 127。
除了 Integer 可以通过参数改变范围外,其它的都不行。
创作打卡挑战赛 赢取流量/现金/CSDN周边激励大奖以上是关于Java Integer 缓存特性(Integer最大/小值探究整型的自动装箱)的主要内容,如果未能解决你的问题,请参考以下文章