Integer源码分析
Integer中包含了大量的static方法。
1.分析Integer的缓存机制:首先定义了一个缓存区,IntegerCache,其实就是一个Integer数组cache[],它默认存储了从-128~127这些Integer对象。
1 private static class IntegerCache { 2 static final int low = -128; 3 static final int high; 4 static final Integer cache[]; 5 6 static { 7 // high value may be configured by property 8 int h = 127; 9 String integerCacheHighPropValue = 10 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); 11 if (integerCacheHighPropValue != null) { 12 int i = parseInt(integerCacheHighPropValue); 13 i = Math.max(i, 127); 14 // Maximum array size is Integer.MAX_VALUE 15 h = Math.min(i, Integer.MAX_VALUE - (-low) -1); 16 } 17 high = h; 18 19 cache = new Integer[(high - low) + 1]; 20 int j = low; 21 for(int k = 0; k < cache.length; k++) 22 cache[k] = new Integer(j++); 23 } 24 25 private IntegerCache() {} 26 }
调用该内部类的代码是valueOf方法,
在这里的assert IntegerCache.high >= 127 我认为是用于加载IntegerCache并执行static初始化代码段使用的(好像也不对,因为后面if语句中也可以初始化,???????请大神指正)。
1 public static Integer valueOf(int i) { 2 assert IntegerCache.high >= 127; 3 if (i >= IntegerCache.low && i <= IntegerCache.high) 4 return IntegerCache.cache[i + (-IntegerCache.low)]; 5 return new Integer(i); 6 }
2.getInteger方法用于获取对应系统字符串代表的整形数,如果想要直接获取字符串代表的整形数,使用decode()方法,如decode(“123”) ----> 123
1 public static Integer getInteger(String nm) { 2 return getInteger(nm, null); 3 } 4 5 public static Integer getInteger(String nm, int val) { 6 Integer result = getInteger(nm, null); 7 return (result == null) ? Integer.valueOf(val) : result; 8 } 9 10 public static Integer getInteger(String nm, Integer val) { 11 String v = null; 12 try { 13 v = System.getProperty(nm); 14 } catch (IllegalArgumentException e) { 15 } catch (NullPointerException e) { 16 } 17 if (v != null) { 18 try { 19 return Integer.decode(v); 20 } catch (NumberFormatException e) { 21 } 22 } 23 return val; 24 }
getInteger方法最终调用decode方法返回整数,decode方法如下:其实最终调用的还是方法parseInt,这里只是将字符串的前缀判断一下,数字的部分用parseInt方法获取结果
1 public static Integer decode(String nm) throws NumberFormatException { 2 int radix = 10; 3 int index = 0; 4 boolean negative = false; 5 Integer result; 6 7 if (nm.length() == 0) 8 throw new NumberFormatException("Zero length string"); 9 char firstChar = nm.charAt(0); 10 // Handle sign, if present 11 if (firstChar == '-') { 12 negative = true; 13 index++; 14 } else if (firstChar == '+') 15 index++; 16 17 // Handle radix specifier, if present 18 if (nm.startsWith("0x", index) || nm.startsWith("0X", index)) { 19 index += 2; 20 radix = 16; 21 } 22 else if (nm.startsWith("#", index)) { 23 index ++; 24 radix = 16; 25 } 26 else if (nm.startsWith("0", index) && nm.length() > 1 + index) { 27 index ++; 28 radix = 8; 29 } 30 31 if (nm.startsWith("-", index) || nm.startsWith("+", index)) 32 throw new NumberFormatException("Sign character in wrong position"); 33 34 try { 35 result = Integer.valueOf(nm.substring(index), radix); 36 result = negative ? Integer.valueOf(-result.intValue()) : result; 37 } catch (NumberFormatException e) { 38 // If number is Integer.MIN_VALUE, we'll end up here. The next line 39 // handles this case, and causes any genuine format error to be 40 // rethrown. 41 String constant = negative ? ("-" + nm.substring(index)) 42 : nm.substring(index); 43 result = Integer.valueOf(constant, radix); 44 } 45 return result; 46 }
3.parseInt方法,该方法将为纯数字的字符串以规定的进制radix(2~36,查看Character类可得到)转为相应的int数字
1 public static int parseInt(String s, int radix) 2 throws NumberFormatException 3 { 4 /* 5 * WARNING: This method may be invoked early during VM initialization 6 * before IntegerCache is initialized. Care must be taken to not use 7 * the valueOf method. 8 */ 9 10 if (s == null) { 11 throw new NumberFormatException("null"); 12 } 13 14 if (radix < Character.MIN_RADIX) { 15 throw new NumberFormatException("radix " + radix + 16 " less than Character.MIN_RADIX"); 17 } 18 19 if (radix > Character.MAX_RADIX) { 20 throw new NumberFormatException("radix " + radix + 21 " greater than Character.MAX_RADIX"); 22 } 23 24 int result = 0; 25 boolean negative = false; 26 int i = 0, len = s.length(); 27 int limit = -Integer.MAX_VALUE; 28 int multmin; 29 int digit; 30 31 if (len > 0) { 32 char firstChar = s.charAt(0); 33 if (firstChar < '0') { // Possible leading "+" or "-" 34 if (firstChar == '-') { 35 negative = true; 36 limit = Integer.MIN_VALUE; 37 } else if (firstChar != '+') 38 throw NumberFormatException.forInputString(s); 39 40 if (len == 1) // Cannot have lone "+" or "-" 41 throw NumberFormatException.forInputString(s); 42 i++; 43 } 44 multmin = limit / radix; 45 while (i < len) { 46 // Accumulating negatively avoids surprises near MAX_VALUE 47 digit = Character.digit(s.charAt(i++),radix); 48 if (digit < 0) { 49 throw NumberFormatException.forInputString(s); 50 } 51 if (result < multmin) { 52 throw NumberFormatException.forInputString(s); 53 } 54 result *= radix; 55 if (result < limit + digit) { 56 throw NumberFormatException.forInputString(s); 57 } 58 result -= digit; 59 } 60 } else { 61 throw NumberFormatException.forInputString(s); 62 } 63 return negative ? result : -result; 64 } 65 66 public static int parseInt(String s) throws NumberFormatException { 67 return parseInt(s,10); 68 }
4.静态的toString方法:源代码的实现方式比较奇怪,先贴在这里:
//一个代表整形的串中可能出现的字符 所组成的数组 final static 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' }; //将整形以对应的基数radix转为字符串 public static String toString(int i, int radix) { if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) radix = 10; /* Use the faster version */ if (radix == 10) { return toString(i); } char buf[] = new char[33]; boolean negative = (i < 0); int charPos = 32; if (!negative) { i = -i; } while (i <= -radix) { buf[charPos--] = digits[-(i % radix)]; i = i / radix; } buf[charPos] = digits[-i]; if (negative) { buf[--charPos] = '-'; } return new String(buf, charPos, (33 - charPos)); } public static String toHexString(int i) { return toUnsignedString(i, 4); } public static String toOctalString(int i) { return toUnsignedString(i, 3); } public static String toBinaryString(int i) { return toUnsignedString(i, 1); } //shift表示将基数左移的位数,然后 private static String toUnsignedString(int i, int shift) { char[] buf = new char[32]; int charPos = 32; int radix = 1 << shift; int mask = radix - 1; do { buf[--charPos] = digits[i & mask]; i >>>= shift; } while (i != 0); return new String(buf, charPos, (32 - charPos)); } final static char [] DigitTens = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', '9', '9', '9', '9', '9', '9', '9', '9', '9', '9', } ; final static char [] DigitOnes = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', } ; public static String toString(int i) { if (i == Integer.MIN_VALUE) return "-2147483648"; int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); char[] buf = new char[size]; getChars(i, size, buf); return new String(buf, true); } static void getChars(int i, int index, char[] buf) { int q, r; int charPos = index; char sign = 0; if (i < 0) { sign = '-'; i = -i; } // Generate two digits per iteration while (i >= 65536) { q = i / 100; // really: r = i - (q * 100); r = i - ((q << 6) + (q << 5) + (q << 2)); i = q; buf [--charPos] = DigitOnes[r]; buf [--charPos] = DigitTens[r]; } // Fall thru to fast mode for smaller numbers // assert(i <= 65536, i); for (;;) { q = (i * 52429) >>> (16+3); r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ... buf [--charPos] = digits [r]; i = q; if (i == 0) break; } if (sign != 0) { buf [--charPos] = sign; } } final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, Integer.MAX_VALUE }; // Requires positive x static int stringSize(int x) { for (int i=0; ; i++) if (x <= sizeTable[i]) return i+1; }