Integer源码分析:
1.Integer的取值范围
Integer中定义的范围为 MIN_VALUE = 0x80000000,MAX_VALUE = 0x7fffffff,大约为-21亿~ +21亿。
2.toString方法
Integer的toString方法有3个,
1.toString()
该方法默认调用toString(int i),并将自己的值作为参数。
2.toString(int i)//只能处理十进制的Integer
public static String toString(int i) {
if (i == Integer.MIN_VALUE)
return "-2147483648";//必须这样处理最小值,因为下面的getChars(i, size, buf)会把负数转化成正数
来取每一位数字,Integer最小值的绝对值比最大值大1,会越界,顾需要单独处理
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);//取Integer的位数,负数因为有负号,要加1,
stringSize()见下面
char[] buf = new char[size];
getChars(i, size, buf);//取每一位的数字,详情见下面
return new String(buf, true);
}
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE };
static int stringSize(int x) {
for (int i=0; ; i++)
if (x <= sizeTable[i])//与sizeTable比较,确定Integer的位数
return i+1;
}
static void getChars(int i, int index, char[] buf) {
int q, r;
int charPos = index;
char sign = 0;
if (i < 0) {
sign = '-';//确定正负数
i = -i;//将负数转化为正数处理,提高效率
}
while (i >= 65536) {//将值判断大小后取每个数字,较大的数字一次取两位(大数字运算消耗大),
变为小数字后使用下面小数字的方法取每一位数字,性能更好,效率更高
q = i / 100;
r = i - ((q << 6) + (q << 5) + (q << 2));//此处使用了位运算(2*6+2*5+2*2=100),
位运算的效率高于乘法,此处结果为一个两位数(个位和十位)
i = q;//重新赋值,准备下一次循环
buf [--charPos] = DigitOnes[r];//取个位的数字,默认数组请看下面
buf [--charPos] = DigitTens[r];//取十位数字
}
for (;;) {//小数字运算消耗较小,故一次只取一位较划算
q = (i * 52429) >>> (16+3);//52429/(2*19)约等于1,此处这样设计是为了提高精度
r = i - ((q << 3) + (q << 1));//即r=i-10q,此处采用位运算,相较于乘法消耗较小
buf [--charPos] = digits [r];//取最后一位的数字
i = q;//重新赋值,准备下一次循环
if (i == 0) break;
}
if (sign != 0) {
buf [--charPos] = sign;
}
}
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',
} ;
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'
};
3.toString(int i,int radix)//处理各种进制的Integer
public static String toString(int i, int radix) {
if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
radix = 10;//即当传入的进制数小于2或大约36时,默认为10,而不是报错
/* Use the faster version */
if (radix == 10) {
return toString(i);
}
char buf[] = new char[33];//2*32约为41亿,才能放下21亿的Integer值,加上一位正负号,为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] = '-';//为负数在buf[0]加上负号
}
return new String(buf, charPos, (33 - charPos));
}
3.Integer.hashcode()
Integer的hashcode就是其本身的值(value),未做任何处理。
4.static class IntegerCache
该类缓存了-128~127的值,在jvm启动时便创建,当程序中直接使用这些值时,边不需创建,直接可以使用这里的值,故此会发生以下的事情
public static void main(String[] args) {
Integer a=5;
Integer b=5;
Integer c=new Integer(5);
Integer d=128;
Integer e=128;
Integer f=new Integer(128);
System.out.println(a==b);//true,取的是缓存中的Integer,两者为同一个5
System.out.println(a==c);//false,a取的是缓存中的5,c是新建的5对象,两者地址值不同
System.out.println(d==e);//false,128已经超出缓存范围,java将新建128的Integer,
d和e各自创建了一个128的Integer,地址值不同
System.out.println(d==f);//false,理由同上,d和f各自创建了一个128的Integer对象,地址值不同
}
5.Integer.parseInt
parseInt(String s)只能将数字字符串转化十进制数,若要转化为其余进制数,则需要使用parseInt(String s, int radix)方法,第二个参数为指定的进制数
public static int parseInt(String s, int radix)
throws NumberFormatException
{
if (s == null) {
throw new NumberFormatException("null");
}
if (radix < Character.MIN_RADIX) {
throw new NumberFormatException("radix " + radix +
" less than Character.MIN_RADIX");
}
if (radix > Character.MAX_RADIX) {
throw new NumberFormatException("radix " + radix +
" greater than Character.MAX_RADIX");
}
int result = 0;
boolean negative = false;
int i = 0, len = s.length();
int limit = -Integer.MAX_VALUE;
int multmin;
int digit;
if (len > 0) {
char firstChar = s.charAt(0);
if (firstChar < '0') {
if (firstChar == '-') {
negative = true;//判断是否为负数
limit = Integer.MIN_VALUE;//将限制转换为Integer的最小值
} else if (firstChar != '+')
throw NumberFormatException.forInputString(s);//第一个char不为+也不为-,则抛出异常
if (len == 1)
throw NumberFormatException.forInputString(s);//若只有一个符号,则抛出异常
i++;
}
multmin = limit / radix;//设定不同进制下的极限值
while (i < len) {
// Accumulating negatively avoids surprises near MAX_VALUE
digit = Character.digit(s.charAt(i++),radix);//将数字字符串转换成要求的进制数
if (digit < 0) {
throw NumberFormatException.forInputString(s);
}
if (result < multmin) {
throw NumberFormatException.forInputString(s);
}
result *= radix;
if (result < limit + digit) {
throw NumberFormatException.forInputString(s);
}
result -= digit;
}
} else {
throw NumberFormatException.forInputString(s);
}
return negative ? result : -result;
}