Integer缓存机制java
总结:面试
一、jdk1.5对Integer新增了缓存机制,范围在-128-127(这个范围的整数值使用频率最高)内的自动装箱返回的是缓存对象,不会new新的对象,因此只要在缓存范围内值相等自动装箱返回的对象同样。jdk1.6后缓存范围的最大值127能够经过设置jvm的启动参数(-XX:AutoBoxCacheMax=size)调整
二、Integer的缓存只在自动装箱时有效,使用构造器(new)建立的对象不会触发缓存
三、int和Integer比较时不用考虑缓存问题,由于Integer会自动拆箱为int再和int比较,这时只是单纯的比较值是否相等数组
详解:
针对Integer常见的一个面试题为缓存
Integer i1 = 100; Integer i2 = 100; Integer j1 = 200; Integer j2 = 200; System.out.println(i1 == i2); // 输出 true System.out.println(j1 == j2); // 输出 false
咱们对于Integer最基本的理解是Integer是int的包装类,是引用数据类型,引用数据类型用==比较的是对象的内存地址。
咱们来看i1的建立过程(jdk1.8)
首先会对Integer i1 = 100;自动装箱(其实就是调用valueOf方法),java会把这段编译为Integer i1 = Integer.valueOf(100),能够自行查看class文件验证。
而后再看Integer.valueOf方法:jvm
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
能够清楚的看到是先从IntegerCache取值,IntegerCache.low IntegerCache.high 范围外则直接new对象(new的对象会存在堆内存中)ide
咱们再来看IntegerCache类,IntegerCache为Integer的私有静态类ui
1 /** 2 * Cache to support the object identity semantics of autoboxing for values between 3 * -128 and 127 (inclusive) as required by JLS. 4 * 5 * The cache is initialized on first usage. The size of the cache 第一次使用时生效 6 * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option. 可经过参数设置最大值 7 * During VM initialization, java.lang.Integer.IntegerCache.high property 8 * may be set and saved in the private system properties in the 9 * sun.misc.VM class. 10 */ 11 12 private static class IntegerCache { 13 static final int low = -128; 14 static final int high; 15 static final Integer cache[]; 16 17 static { 18 // high value may be configured by property 19 int h = 127; 20 String integerCacheHighPropValue = 21 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); 22 if (integerCacheHighPropValue != null) { 23 try { 24 int i = parseInt(integerCacheHighPropValue); 25 i = Math.max(i, 127); 26 // Maximum array size is Integer.MAX_VALUE 27 h = Math.min(i, Integer.MAX_VALUE - (-low) -1); 28 } catch( NumberFormatException nfe) { 29 // If the property cannot be parsed into an int, ignore it. 30 } 31 } 32 high = h; 33 34 cache = new Integer[(high - low) + 1]; 35 int j = low; 36 for(int k = 0; k < cache.length; k++) 37 cache[k] = new Integer(j++); 38 39 // range [-128, 127] must be interned (JLS7 5.1.7) 40 assert IntegerCache.high >= 127; 41 } 42 43 private IntegerCache() {} 44 }
Integer的缓存经过for循环建立存放到一个数组中,注释已经解释该数组会在Integer第一次使用时初始化,结合类加载顺序来理解,第一次使用Integer时内部静态类会被初始化,静态代码块会被执行,存到堆中。会有第一次惩罚spa
jdk1.5源码参考.net
1 private static class IntegerCache { 2 static final Integer[] cache = new Integer[256]; 3 4 static { 5 for (int i = 0; i < cache.length; i++) { 6 cache[i] = new Integer(i - 128); 7 } 8 } 9 } 10 11 public static Integer valueOf(int paramInt) { 12 if ((paramInt >= -128) && (paramInt <= 127)) { 13 return IntegerCache.cache[(paramInt + 128)]; 14 } 15 return new Integer(paramInt); 16 }
Integer与int用==比较时Integer会自动拆箱(调用intValue()方法)为int进行比较
i1 == 100 会编译成 i1.intValue() == 100code
其余缓存的对象
这种缓存行为不只适用于Integer对象。咱们针对全部整数类型的类都有相似的缓存机制。
有 ByteCache 用于缓存 Byte 对象
有 ShortCache 用于缓存 Short 对象
有 LongCache 用于缓存 Long 对象
有 CharacterCache 用于缓存 Character 对象
Byte,Short,Long 有固定范围: -128 到 127。对于 Character, 范围是 0 到 127。除了 Integer 能够经过参数改变范围外,其它的都不行。
参考博文:https://blog.csdn.net/qq_27093465/article/details/52473649
int与Integer(基本类型与包装类型)
Integer是int的包装类型,二者的区别为:
一、int初始值为0,Integer初始值为null,全部的引用类型都为null;
二、Integer为引用类型,对象存放在堆中。int为基本数据类型,对象存放在栈中;
使用包装类的好处:
一、Integer封装了不少处理方法,方便操做,好比进制转化(toBinaryString)、数据类型之间的转化(toString);
二、解决有些类型不支持基础数据类型的状况,好比List只能接收引用类型;
至于什么时候使用基本数据类型,什么时候使用包装类型这个就要看具体需求,当只是做为数值不须要更多的操做时用基本类型就可,灵活使用
基本数据类型和对应的包装类
int——Integer
float——Float
double——Double
byte——Byte
long——Long
char——Character
boolean——Boolean
short——Short
自动拆装箱(jdk1.5引入)
自动拆箱实际上就是引用类型自动转化成基本数据类型,自动装箱实际上就是基本数据类型自动转化成对应的引用类型
好比建立Integer i = new Integer(100); 能够直接写成Integer i = 100;不须要强转 (自动装箱)
int j = i 基本数据类型j能够直接等于引用类型i (自动拆箱)
1 Integer i = 1; 2 int j = i; 3 4 /** 5 * 上面代码编译成class后 6 */ 7 Integer i = Integer.valueOf(1); 8 int j = i.intValue();
由上能够看出自动装箱实际上就是调用了valueOf方法,自动拆箱调用了intValue方法