publicclassIntegerDemo{ publicstaticvoidmain(String[] args){ Integer a = new Integer(8); Integer b = Integer.valueOf(8); Integer c = 8; System.out.println(a.equals(b)); System.out.println(a.equals(c)); System.out.println(b.equals(c));
publicclassIntegerDemo{ publicstaticvoidmain(String[] args){ Integer a = new Integer(128); Integer b = Integer.valueOf(128); Integer c = 128; System.out.println(a.equals(b)); System.out.println(a.equals(c)); System.out.println(b.equals(c));
publicstatic Integer valueOf(String s)throws NumberFormatException { return Integer.valueOf(parseInt(s, 10)); } //@HotSpotIntrinsicCandidate 这个注解是JDK9才引入的 //HotSpot 虚拟机将对标注了@HotSpotIntrinsicCandidate注解的方法的调用, //替换为直接使用基于特定 CPU 指令的高效实现。这些方法我们便称之为 intrinsic。 publicstatic Integer valueOf(int i){ //如果i在low和high之间就使用缓存 if (i >= IntegerCache.low && i <= IntegerCache.high){ return IntegerCache.cache[i + (-IntegerCache.low)]; } returnnew Integer(i); }
上面valueOf()方法中用到了IntegerCache,下面我们来聊聊。
IntegerCache
下面是IntegerCache源码和部分注释:
/** * Cache to support the object identity semantics of autoboxing for values between * -128 and 127 (inclusive) as required by JLS. * JLS协议要求缓存在-128到127之间(包含边界值) * * The cache is initialized on first usage. * 程序第一次使用Integer的时候 * The size of the cache may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option. * JVM 的启动参数 -XX:AutoBoxCacheMax=size 修改最大值 * 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. * 可以通过系统属性来获得:-Djava.lang.Integer.IntegerCache.high=<size> */ privatestaticclassIntegerCache{ staticfinalint low = -128; staticfinalint high; //使用数组来缓存常量池 staticfinal Integer cache[];
static { // high value may be configured by property //最大值是可以配置的 int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); //如果有配置-XX:AutoBoxCacheMax=<size> if (integerCacheHighPropValue != null) { try { int i = parseInt(integerCacheHighPropValue); //和127进行比较,谁大用谁 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. // 如果该值配置错误则忽略该参数配置的值,使用默认范围-128~127 } } high = h;
cache = new Integer[(high - low) + 1]; int j = low; // 缓存通过for循环来实现,创建范围内的整数对象并存储到cache数组中 // 程序第一次使用Integer的时候需要一定的额外时间来初始化该缓存 for(int k = 0; k < cache.length; k++){ cache[k] = new Integer(j++); } //无论如何,缓存的最大值肯定是大于等于127 assert IntegerCache.high >= 127; } //私有的构造方法,因为所有的属性均属于类常量 privateIntegerCache(){} }
整个静态块:
那么,如何设置java.lang.Integer.IntegerCache.high的值呢?
The size of the cache may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
注释中已经说清楚,可以使用-XX:AutoBoxCacheMax=<size>设置。
写个demo来debug看看
publicclassIntegerDemo{ publicstaticvoidmain(String[] args){ Integer a = 8; Integer b =Integer.valueOf(8); System.out.println(a.equals(b)); System.out.println(a == b); } }
设置`-XX:AutoBoxCacheMax`=100
开始debug
看看high的值
是127,那就对了,因为上面
设置`-XX:AutoBoxCacheMax`=130
开启debug模式
注意:low=-128是不会变的,整个缓存初始化过程并没有对low进行修改,再说low是常量。
-XX:AutoBoxCacheMax最大能设置成多大?
因为Integer的最大值是2147483647 ,所以我们这里使用这个值试试,
开始debug,直接报OOM了
为什么会OOM呢?
如果-XX:AutoBoxCacheMax没有设置值,那么对应数组是这样的。
equals()方法
上面的案例中有equals方法,这里把这个方法也拿出来聊聊
privatefinalint value; publicbooleanequals(Object obj){ if (obj instanceof Integer) { //这里比较的是两个int类型的值 return value == ((Integer)obj).intValue(); } //obj不是Integer类型直接返回false returnfalse; }
回到上面的案例中
当我们使用equals方法比较两个对象是否相等的时候其实就是比较他们的value值。
所以不管是128还是8,equals后肯定都是true。
当引用类型使用==进行比较的时候,此时比较的是两个引用的对象的地址,是不是同一个。
publicclassIntegerDemo{ publicstaticvoidmain(String[] args){ Integer a = new Integer(8); Integer b = Integer.valueOf(8); Integer c = 8; System.out.println(a.equals(b)); System.out.println(a.equals(c)); System.out.println(b.equals(c));