请回答下这两个Integer相等不
第一组
Integer a=127;
Integer b=127;
System.out.println(a==b);
第二组
Integer a=128;
Integer b=128;
答案是第一组输出true,第二组输出false。
补充下,为什么?
首先debug这行代码: Integer a=1;
它会进入Integer.valueOf(int n)这个方法,这个与普通的java类的初始化方法是不一样的。下面的源码这有个方法的实现。
看下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 * sun.misc.VM class. 缓存-128到127的数字,这个缓存在第一阶段初始化(这里说的是Jvm初始化,所以我们debug断点是打不到的)。 可以使用jvm参数(-XX:AutoBoxCacheMax=<size>)控制缓存大小,初始化参数java.lang.Integer.IntegerCache.high。 */ 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) { 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() {} } public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
从上面源码可以看出:
1.这个问题来源于,Integer有个IntegerCache,取值时(ValueOf)会先从这个cache取。
2.cache范围,可以设置-XX:AutoBoxCacheMax=
System.out.println(Integer.toBinaryString(Integer.MAX_VALUE)+":"+Integer.MAX_VALUE); System.out.println(Integer.toBinaryString(Integer.MIN_VALUE)+":"+Integer.MIN_VALUE);输出:
1111111111111111111111111111111:2147483647 10000000000000000000000000000000:-2147483648可以看出Integer.MAX_VALUE的二进制形式比Integer.MIN_VALUE少一位,因为它第一位是0,未显示出来。
求负整数的补码,将其原码除符号位外的所有位取反(0变1,1变0,符号位为1不变)后加1。
System.out.println(Integer.MAX_VALUE+":"+(Double.valueOf(Math.pow(2, 31)).longValue()-1));输出:
2147483647:2147483647说明这个计算没有问题。
public static String toBinaryString(int i) { return toUnsignedString0(i, 1); } /** * Convert the integer to an unsigned number. */ private static String toUnsignedString0(int val, int shift) { // assert shift > 0 && shift <=5 : "Illegal shift value"; int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val); int chars = Math.max(((mag + (shift - 1)) / shift), 1); if (COMPACT_STRINGS) { byte[] buf = new byte[chars]; formatUnsignedInt(val, shift, buf, 0, chars); return new String(buf, LATIN1); } else { byte[] buf = new byte[chars * 2]; formatUnsignedIntUTF16(val, shift, buf, 0, chars); return new String(buf, UTF16); } }
static void formatUnsignedInt(int val, int shift, byte[] buf, int offset, int len) { int charPos = offset + len; int radix = 1 << shift; int mask = radix - 1; do { buf[--charPos] = (byte)Integer.digits[val & mask]; val >>>= shift; } while (charPos > offset); }
/** * All possible chars for representing a number as a String */ static final char[] digits = { '0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' , 'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' , 'x' , 'y' , 'z' };
/* * @param i the value whose number of leading zeros is to be computed * @return the number of zero bits preceding the highest-order * ("leftmost") one-bit in the two's complement binary representation * of the specified {@code int} value, or 32 if the value * is equal to zero. * @since 1.5 */ @HotSpotIntrinsicCandidate public static int numberOfLeadingZeros(int i) { // HD, Figure 5-6 if (i == 0) return 32; int n = 1; if (i >>> 16 == 0) { n += 16; i <<= 16; } if (i >>> 24 == 0) { n += 8; i <<= 8; } if (i >>> 28 == 0) { n += 4; i <<= 4; } if (i >>> 30 == 0) { n += 2; i <<= 2; } n -= i >>> 31; return n; }返回最左边的0的个数。这些0有两部分,第1位是补码(符号位)。如果是0返回32位。
传入参数即可以是正数,也可以是负数。如果是正数则符号位是0,算是一个0.如果是负数则符号位是1,那么返回一定是0.以3为例,3的2进制形式是:
00000000000000000000000000000011
Map
这个gradeId本来是个Integer,这儿却要写成String。因为如果是Integer,在返回后直接取map.get(3),这样的会取不到。